map
Map是一系列有一个键值(key)和映射值(value)组合的存储元素关联容器。
在一个map中,key值是唯一的确定一个元素,而映射值(value)是这个key相关的值的某个排序。键的类型和值的类型是不同的,例如,map的一个典型的实例----电话簿索引是以姓名作为key,以电话号码作为value的。
本质上,map中的元素是从低到高的键值排序伴随着一个设置在构造函数中严格的弱排序的标准。
作为关联容器,他们特别设计了通过键值快速访问(不像通过相关联或者相对位置快速访问的顺序容器)。
因此,下面是map作为关联容器的几个主要特征:
- 唯一的键值:在map容器中,每个键值都是唯一的。
- 每一个元素都是有键和值组成。元素值即为其键的简单的关联容器,需要看一下set关联容器。
- 元素始终保持着严格的弱排序。
map中的键唯致使此关联容器可以直接执行访问操作(operator[]),此访问操作允许访问值。
在c++标准模板库的说明文档中,map容器有四个模板参数:
- template<class Key, class T., class Compare = less<Key>, class Allocator = allocator<pair<const Key,T> > > class map;
参数解析:
- Key:键值的类型,map容器的每一个元素都是唯一的有键值确定。
- T:映射值的类型,map中的每一个元素都是用于存储某些数据作为其映射值。
- Compare:比较类:一个带有两个键类型的参数和返回一个布尔值(bool)。表达式comp(a, b),comp是比较类的对象,a和b是键值,如果a在b之前(类似a<b),返回true;也可以是执行函数操作的类或者一个指向函数的指针。它默认为less<Key>,其中less<Key>和a<b返回的值类似。map对象用这个表达式决定元素在容器中的位置。所有在map容器着哦功能的元素都始终遵守这个规则。
- Allocator:用于定义存储分配模型的分配器对象类型,默认的情况下,使用allocator类模板,这个类模板是最简单的内存分配模型并且是值独立的。
这个容器类支持双向迭代。
迭代器访问map容器元素的key和value。为此,类定义了value_type类型,此类型是一个第一个值为对应的常key类型(模板参数Key)和第二个值对应的value(模板参数为T)的pair类:
typedef pair<const Key, T> value_type;
map容器的迭代器指向value_type类型的元素,因此,对于一次迭代调用,可以指向map元素,此元素的key和value都可以分别访问到:
- map<Key, T>::iterator it;
- (*it).first;
- (*it).second;
- (*it)
当然,任何其他的直接访问操作,例如->或者[]可以使用,例如:
成员函数
-
(constructor)
-
map容器的构造函数。
-
(destructor)
-
Map容器的析构函数。
-
operator=
-
拷贝容器内容。
迭代器
:
-
begin
-
返回第一个元素的迭代器。
-
end
-
返回最后一个元素的下一个为位置的迭代器
-
rbegin
-
返回指向反向第一个位置的反向迭代器
-
rend
-
返回指向最后一个元素的下一个位置的反向迭代器
容器(Capacity)
:
-
empty
-
测试容器是否为空
-
size
-
返回容器大小
-
max_size
-
返回最大的值
元素访问
:
-
operator[]
-
访问元素。
修改容器操作
:
-
insert
-
插入元素
-
erase
-
擦除元素
-
swap
-
交换内容(指不同的map容器之间交换)
-
clear
-
清空容器
观察者(Observers)
:
-
key_comp
-
返回键值比较对象。
-
value_comp
-
返回映射值比较对象。
操作
:
-
find
-
获取元素迭代器
-
count
-
计算指定key元素的个数,由于map容器的特点,此值只能取0和1中的一个。
-
lower_bound
-
返回一个迭代器,指向
键值>= key的第一个元素。
-
upper_bound
-
返回一个迭代器,指向
键值> key的第一个元素。
-
equal_range
-
Get range of equal elements
分配器
:
-
get_allocator
-
获取容器对象
成员类型
of template <class Key, class T, class Compare=less<Key>, class Allocator=allocator<pair <const Key, T> > > class map;
member type |
definition |
key_type |
Key |
mapped_type |
T |
value_type |
pair<const Key,T> |
key_compare |
Compare |
value_compare |
Nested class to compare elements (see member function value_comp) |
allocator_type |
Allocator |
reference |
Allocator::reference |
const_reference |
Allocator::const_reference |
iterator |
Bidirectional iterator |
const_iterator |
Constant bidirectional iterator |
size_type |
Unsigned integral type (usually same as size_t) |
difference_type |
Signed integral type (usually same as ptrdiff_t) |
pointer |
Allocator::pointer |
const_pointer |
Allocator::const_pointer |
reverse_iterator |
reverse_iterator<iterator> |
const_reverse_iterator |
reverse_iterator<const_iterator> |
map::map
explicit map ( const Compare& comp = Compare(),
const Allocator& = Allocator() );
template <class InputIterator>
map ( InputIterator first, InputIterator last,
const Compare& comp = Compare(), const Allocator& = Allocator() );
map ( const map<Key,T,Compare,Allocator>& x );
(Key, T, Compare and Allocator
map构造函数
构造一个map容器对象,依据下面的构造函数初始化容器内容:
explicit map ( const Compare& comp = Compare(), Allocator& = Allocator() );
默认构造函数:构造一个空的map对象,这个对象没有内容并且大小为0。
template <class InputIterator>
map ( InputIterator first, InputIterator last, const Compare& comp= Compare(), const Allocator& = Allocator() );
迭代构造函数:在第一个和最后一个之间迭代,设定每个元素序列的拷贝作为容器对象的内容。
map ( const map<Key,T,Compare,Allocator>& x );
拷贝构造函数:对象初始化为和x对象有着相同的内容和属性。
参数
first, last
容器序列中的第一个位置和最后一个位置的输入迭代器,范围为[first,last),包括所有的在first和last之间的元素,其中last是容器中最后一个元素的下一个位置。函数模板类型是任意的输入迭代器 的类型。
x
有着相同的类模板参数(Key,T,Compare and Allocator)的另一个map对象。
comp
用于严格的弱排序(weak ordering)的比较对象。
Compare是第三个类模板参数。
unnamed Allocator parameter
用于替代构造一个新的Allocator对象。
对于类实例采用默认分配器类模板的版本,这个参数是不相关的。
实例
-
- #include <iostream>
- #include <map>
- using namespace std;
-
- bool fncomp (char lhs, char rhs) {return lhs<rhs;}
-
- struct classcomp {
- bool operator() (const char& lhs, const char& rhs) const
- {return lhs<rhs;}
- };
-
- int main ()
- {
- map<char,int> first;
-
- first['a']=10;
- first['b']=30;
- first['c']=50;
- first['d']=70;
-
- map<char,int> second (first.begin(),first.end());
-
- map<char,int> third (second);
-
- map<char,int,classcomp> fourth;
-
- bool(*fn_pt)(char,char) = fncomp;
- map<char,int,bool(*)(char,char)> fifth (fn_pt);
-
- return 0;
- }
map::count
size_type count ( const key_type& x ) const;
计算map中指定key出现的次数,由于map容器中key值是不允许重复的,所以函数实际返回的是:1,指定的key在容器中;0,指定的key不在容器中。
参数
-
x
需要搜索的key值。key_type是一个map容器的成员类型,是key的一个别名。
返回值
如果容器中有指定key的元素,返回1,或者返回0。
size_type成员类型是一个无符号的整数类型。
举例
- #include <iostream>
- #include <map>
-
- using namespace std;
-
- int main()
- {
- map<char, int> mymap;
- char c;
-
- mymap['a'] = 101;
- mymap['c'] = 202;
- mymap['f'] = 303;
-
- for (c='a'; c<'h'; c++)
- {
- cout << c;
- if (mymap.count(c)>0)
- {
- cout << " is an element of mymap." << endl;
- }
- else
- {
- cout << " is not an element of mymap." << endl;
- }
- }
- return 0;
- }
执行结果
- liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_count
- a is an element of mymap.
- b is not an element of mymap.
- c is an element of mymap.
- d is not an element of mymap.
- e is not an element of mymap.
- f is an element of mymap.
- g is not an element of mymap.
map::insert
- pair<iterator,bool> insert(const value_type& x);
- iterator insert(iterator position, const value_type& x);
- template<class InputIterator>
- void insert(InputIterator first, InputIterator last);
插入元素
map容器可以插入单个新元素(如果使用参数x)或者元素序列(如果使用输入迭代器)。
随着插入元素数量增加,容器的size也随着增加。
由于map容器不允许键值重复,所以插入操作需要确保要插入的key值在map容器中没有。如果有的话,新的元素是不允许插入的,并且此键值的映射值是不会发生改变的。
如果想允许插入相同的元素,可以参考multimap。
本质上,map容器保持所有元素按照结构体指定的比较对象排序。
map容器允许直接的访问通过map::operator[]操作(对[]操作符进行了重载),即可以通过object[key]=value;这样操作。
参数
x
初始化插入元素的值。
position
确定插入操作时第一个相比较的元素。该参数并不是强制插入元素的位置。
first,last
指定元素区间的迭代器。拷贝[first,last)区间的元素,并且插入到map容器中。
返回值
第一个版本的insert返回一个pair类型,pair类型的成员pair:first设置一个迭代器指针,这个迭代器指针可能指向新插入的元素或者已经在map容器中存在的有着相同key值的元素;成员pair:second元素,如果新的元素插入,返回为true,或者当已经存在相同的key,返回false。
第二个版本返回一个指向新插入的元素或者已经在map容器中存在的有着相同key值的元素的迭代器指针。
迭代器是一个成员类型,被定义成双向迭代器类型。
举例1:
- #include <string>
- #include <iostream>
- #include <map>
- #include <utility>
-
- using namespace std;
-
- int main(void)
- {
- map<string, int> Employees;
-
- Employees["Mike C."] = 12306;
- Employees["Charlie M."] = 95555;
-
- Employees.insert(std::pair<string, int>("David D.", 1984));
- Employees.insert(map<string, int>::value_type("John A.", 7582));
- Employees.insert(make_pair("Peter Q.", 5328));
-
- cout << "Map size: " << Employees.size() << endl;
-
- for (map<string, int>::iterator ii= Employees.begin(); ii != Employees.end(); ++ii)
- {
- cout << (*ii).first << ":" << (*ii).second << endl;
- }
- return 0;
- }
执行结果:
- liujl@liujl-Rev-1-0:~/mycode/STL$ ./mapEx2
- Map size: 5
- Charlie M.:95555
- David D.:1984
- John A.:7582
- Mike C.:12306
- Peter Q.:5328
实例2:
- #include <iostream>
- #include <map>
-
- using namespace std;
-
- int main(void)
- {
- map<char, int> mymap;
- map<char, int>::iterator it;
- pair<map<char, int>::iterator, bool> ret;
-
-
- mymap.insert( pair<char, int>('a', 100) );
- mymap.insert( make_pair('d', 200) );
- mymap.insert( map<char, int>::value_type('z', 500));
-
-
- ret = mymap.insert( pair<char, int>('z', 800));
- if (ret.second == false)
- {
- cout << " element 'z' already existed!";
- cout << " with a value of " << ret.first->second << endl;
- }
-
-
- it = mymap.begin();
- mymap.insert(it, pair<char, int>('b', 300));
- mymap.insert(it, pair<char, int>('c', 400));
-
-
- map<char, int> othermap;
- othermap.insert(mymap.begin(), mymap.end());
-
-
-
-
- cout << "mymap contains: " << endl;
- for (it = mymap.begin(); it != mymap.end(); it++)
- cout << (*it).first << "=>" << (*it).second << endl;
-
- cout << "other contains: " << endl;
- for (it=othermap.begin(); it != othermap.end(); it++)
- cout << (*it).first << "=>" << (*it).second << endl;
- return 0;
- }
map::find
- iterator find ( const key_type& x );
- const iterator find( const key_type& x) const;
获取元素的迭代器
获取map容器中指定键值x的元素,如果找到,返回此元素的迭代器,否则返回map::end()的迭代器(即查找到容器的末尾都没有找到此元素)。
前面章节介绍的map::count成员函数也可以有类似的功能,详见STL学习之map容器(1)介绍。
参数
x
需要查找的键值。
Key_type是map容器定义的作为Key别名的一个成员类型。
返回值
指向元素的迭代器,如果指定的键值找到,返回找到元素的迭代器或者指定的键值没有找到返回map::end。
实例:
- #include <iostream>
- #include <map>
-
- using namespace std;
-
- int main(void)
- {
- map<char, int> mymap;
- map<char, int>::iterator it;
-
- mymap['a'] = 50;
- mymap['b'] = 100;
- mymap['c'] = 150;
- mymap['d'] = 200;
-
- it = mymap.find('b');
- mymap.erase(it);
- mymap.erase(mymap.find('d'));
-
- cout << "mymap contains:" << endl;
- for (it = mymap.begin(); it != mymap.end(); ++it)
- cout << (*it).first << "=>" << (*it).second << endl;
-
- cout << " elements in mymap:" << endl;
- cout << " a=> " << mymap.find('a')->second << endl;
- cout << " b=> " << mymap.find('b')->second << endl;
- cout << " c=> " << mymap.find('c')->second << endl;
- cout << " d=> " << mymap.find('d')->second << endl;
- return 0;
- }
执行结果:
- liujl@liujl-Rev-1-0:~/mycode/STL$ g++ map_find.cpp -o map_find
- liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_find
- mymap contains:
- a=>50
- c=>150
- elements in mymap:
- a=> 50
- b=> -1076412860
- c=> 150
- d=> -1076412860
map::erase
- void erase( iterator postion );
- size_type erase( const key_type& x );
- void erase( iterator first, iterator last );
删除元素
从map容器中删除一个元素或者一个区间的元素([first, last));
参数
postion
指向被map容器中删除元素迭代器指针。
iterator是一个成员类型,定义作为双向迭代器类型。
x
从map容器中移除的元素值。
first,last
指定迭代器区间[first,last),需要从map容器中删除的区间。
返回值
仅第二个版本,函数返回需要删除的元素个数。
实例:
-
- #include <iostream>
- #include <map>
- using namespace std;
-
- int main ()
- {
- map<char,int> mymap;
- map<char,int>::iterator it;
-
-
- mymap['a']=10;
- mymap['b']=20;
- mymap['c']=30;
- mymap['d']=40;
- mymap['e']=50;
- mymap['f']=60;
-
- it=mymap.find('b');
- mymap.erase (it);
-
- mymap.erase ('c');
-
- it=mymap.find ('e');
- mymap.erase ( it, mymap.end() );
-
-
- for ( it=mymap.begin() ; it != mymap.end(); it++ )
- cout << (*it).first << " => " << (*it).second << endl;
-
- return 0;
- }
执行结果:
- liujl@liujl-Rev-1-0:~/mycode/STL$ g++ map_erase.cpp -o map_erase
- liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_erase
- a => 10
- d => 40
map::lower_bound
- iterator lower_bound( const key_type& x );
- const iterator lower_bound( const key_type& x ) const;
返回指向下界的迭代器
返回一个指向容器中第一个键值大于或者等于x元素迭代器。
map::upper_bound
- iterator upper_bound( const key_type& x );
- const iterator upper_bound( const key_type& x ) const;
返回指向上界的迭代器
返回一个指向容器中第一个键值大于x元素迭代器。
从定义中可以看到upper_bound和lower_bound区别。
upper_bound和lower_bound参数
x
比较的键值。
实例:
- #include <iostream>
- #include <map>
-
- using namespace std;
-
- int main(void)
- {
- map<char, int> mymap;
- map<char, int>::iterator it, itlow, itup;
-
- mymap['a'] = 20;
- mymap['b'] = 40;
- mymap['c'] = 60;
- mymap['d'] = 80;
- mymap['e'] = 100;
-
- itlow = mymap.lower_bound('b');
- itup = mymap.upper_bound('d');
-
- mymap.erase(itlow, itup);
-
- for( it= mymap.begin(); it != mymap.end(); ++it)
- cout << (*it).first << "=>" << (*it).second << endl;
- return 0;
- }
执行结果:
- liujl@liujl-Rev-1-0:~/mycode/STL$ g++ map_bound.cpp -o map_bound
- liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_bound
- a=>20
- e=>100
执行结果:
- liujl@liujl-Rev-1-0:~/mycode/STL$ vim map_insert.cpp
- liujl@liujl-Rev-1-0:~/mycode/STL$ g++ map_insert.cpp -o map_insert
- liujl@liujl-Rev-1-0:~/mycode/STL$ ./map_insert
- element 'z' already existed! with a value of 500
- mymap contains:
- a=>100
- b=>300
- c=>400
- d=>200
- z=>500
- other contains:
- a=>100
- b=>300
- c=>400
- d=>200
- z=>500
std::map的insert和下标[]访问
在map中插入元素
改变map中的条目非常简单,因为map类已经对[]操作符进行了重载
enumMap[1] = "One";
enumMap[2] = "Two";
.....
这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为"Two"; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。我们可以用以下方法来避免开销:
enumMap.insert(map<int, CString> :: value_type(2, "Two"))
insert()方法:若插入的元素的键值已经存在于map中,那么插入就会失败,不会修改元素的键对应的值;若键值在map中查不到,那么就会将该新元素加到map中去。
下标[key]方法:若插入元素的键值已经存在于map中,那么会更新该键值对应的值为新的元素的值;若该键值在map中找不到,那么就会新建一个键值为该键(key)的元素,并将key对应的值赋值为默认值(默认构造函数生成的对象)