简介

  • 谨记 value_type是pair< const K, V>类型的同义词,K为键类型,V为键所关联的值的类型

  • map对象中一个给定键只对应一个元素。如果试图插入的元素所对应的键已经在容器中,则insert 将不做任何操作。

  • 通常来说,下标操作符返回左值。它返回的左值是特定键所关联的值。

  • 有别于vector或string类型,map下标操作符返回的类型与对map迭代器进行解引用获得的类型不相同。

  • map迭代器返回value_type类型的值—––包括const key_type 和mapped_type类型成员的pair对象;下标操作符返回一个mapped_type类型的值。

  • 带有一个键—值pair 形参的insert 版本将返回一个值:包含一个迭代器和一个bool 值的pair 对象。其中迭代器指向map中具有相应键的元素,而bool 值则表示是否插入了该元素。如果该元素已经在容器中,则其关联的值保持不变,返回bool值为false;如果该键不在容器中,则插入新元素,且bool值为true。

=============================================================================================

  • map 容器的insert成员与顺序容器的类似,但有一点要注意:必须考虑键的作用。键影响了实参的类型:插入单个元素的insert版本使用键–值 pair 类型的参数。

  • 类似的,对于参数为一对迭代器的版本,迭代器必须指向键–值 pair 类型的元素。另一个差别则是:map容器的接受单个值的insert版本的返回类型。

这里写图片描述

这里写图片描述

1、以insert代替下标运算

这里写图片描述
- 使用下标给map容器添加新元素时,元素的值部分将采用值初始化。通常,我们会立即为其赋值,其实就是对同一个对象进行初始化并赋值。而插入元素的另一个方法是:直接使用insert 成员

word_count.insert(map<string,int>::value_type("Anna",1));
 
 
  • 1
  • 这个insert 函数的实参是 map< string,int>::value_type(“Anna”,1)。是一个新创建的pair 对象,将直接插入到map 容器中。谨记 value_type是pair< const K, V>类型的同义词,K为键类型,V为键所关联的值的类型

  • insert 的实参创建了一个适当的pair类型新对象,该对象将插入到map容器。

  • 在添加新的map元素时,使用insert 成员可避免使用下标操作符所带来的副作用:不必要的初始化。

    • 传递给insert 的实参相当笨拙,可用两种方式简化: 使用 make_pair 或 typedef
word_count.insert(make_pair("Anna",1));
 
 
  • 1
typedef map<string,int>::value_type valType;
word_count.insert(valType("Anna",1););


例子:

  1. #include <stdio.h>  
  2. #include <string>  
  3. #include <map>  
  4. #include <memory>  
  5. using namespace std;  
  6.   
  7. int _tmain(int argc, _TCHAR* argv[])  
  8. {  
  9.     map<intint> imap;  
  10.     map<intint> jmap;  
  11.     jmap[1] = 1;  
  12.     jmap[2] = 2;  
  13.     imap.insert(jmap.begin(), jmap.end());  
  14.     map<intint>::iterator iter = imap.begin();  
  15.     for (; iter != imap.end(); iter++)  
  16.         printf("iter->first: %d, iter->second: %d\n", iter->first, iter->second);  
  17.     getchar();  
  18.     return 0;  
  19. }  

运行结果如下:
  1. iter->first: 1, iter->second: 1  
  2. iter->first: 2, iter->second: 2  

注意: insert(iter1, iter2)返回值是void


例子:

  1. #include <stdio.h>  
  2. #include <string>  
  3. #include <map>  
  4. #include <memory>  
  5. using namespace std;  
  6.   
  7. int _tmain(int argc, _TCHAR* argv[])  
  8. {  
  9.     map<intint> jmap;  
  10.     jmap[1] = 1;  
  11.     jmap[2] = 2;  
  12.     pair<map<intint>::iterator, bool> pret = jmap.insert(pair<intint>(3, 3));  
  13.     printf("pret.second: %d, pret.first->first: %d, pret.first->second: %d\n", pret.second, pret.first->first, pret.first->second);  
  14.     pret = jmap.insert(pair<intint>(1, 1));  
  15.     printf("pret.second: %d, pret.first->first: %d, pret.first->second: %d\n", pret.second, pret.first->first, pret.first->second);  
  16.     getchar();  
  17.     return 0;  
  18. }  

运行结果为:
  1. pret.second: 1, pret.first->first: 3, pret.first->second: 3  
  2. pret.second: 0, pret.first->first: 1, pret.first->second: 1  

分析:insert(pair<...>) 版本返回值是一个pair结构,其中第一个元素是一个迭代器,第二个元素是一个bool类型,根据以上结果:如果原来的map中不含有插入的元素,则bool为true,迭代器指向插入的元素;如果map中已经含有插入的元素了,则bool为false,返回的迭代器指向对应的map中已经存在的元素


例子:

  1. #include <stdio.h>  
  2. #include <string>  
  3. #include <map>  
  4. #include <memory>  
  5. using namespace std;  
  6.   
  7. int _tmain(int argc, _TCHAR* argv[])  
  8. {  
  9.     map<intint> imap;  
  10.     map<intint> jmap;  
  11.     jmap[1] = 1;  
  12.     jmap[2] = 2;  
  13.     imap.insert(jmap.begin(), jmap.end());  
  14.     map<intint>::iterator ret = imap.insert(imap.begin(), pair<intint>(1, 1));  
  15.     printf("ret->first: %d, ret->end: %d\n", ret->first, ret->second);  
  16.     ret = imap.insert(imap.begin(), pair<intint>(3, 3));  
  17.     printf("ret->first: %d, ret->end: %d\n", ret->first, ret->second);  
  18.     getchar();  
  19.     return 0;  
  20. }  
运行结果为:
  1. ret->first: 1, ret->end: 1  
  2. ret->first: 3, ret->end: 3  
分析:insert(iter, pair<...>)返回一个指向插入元素的迭代器,如果map中已经存在元素,则返回的迭代器指向原先map中已经存在的元素


例子:

  1. #include <stdio.h>  
  2. #include <string>  
  3. #include <map>  
  4. #include <memory>  
  5. using namespace std;  
  6.   
  7. int _tmain(int argc, _TCHAR* argv[])  
  8. {  
  9.     map<intint> kmap;  
  10.     //std::initializer_list<pair<int, int> > list = { pair<int, int>(10, 10), pair<int, int>(20, 20), pair<int, int>(30, 30) }; //error  
  11.     kmap.insert({ pair<intint>(10, 10), pair<intint>(20, 20), pair<intint>(30, 30) });  
  12.     map<intint>::iterator iter = kmap.begin();  
  13.     for (; iter != kmap.end(); iter++)  
  14.         printf("iter->first: %d, iter->second: %d\n", iter->first, iter->second);  
  15.     //MapInsert();  
  16.     getchar();  
  17.     return 0;  
  18. }  


运行结果为:
  1. iter->first: 10, iter->second: 10  
  2. iter->first: 20, iter->second: 20  
  3. iter->first: 30, iter->second: 30  

分析:这里的insert是使用void insert(_XSTD initializer_list<value_type> _Ilist)这个重载版本的,返回值为void,在外面定义initializer_list再传进去会出错,不知道为什么。


例子:

  1. #include <stdio.h>  
  2. #include <string>  
  3. #include <map>  
  4. #include <memory>  
  5. using namespace std;  
  6.   
  7. class People  
  8. {  
  9. public:  
  10.     People(const char* name, int age)  
  11.     {  
  12.         printf("constructor People\n");  
  13.         strcpy(m_name, name);  
  14.         m_age = age;  
  15.     }  
  16.     virtual ~People()  
  17.     {  
  18.         printf("destructor People\n");  
  19.     }  
  20.   
  21. public:  
  22.     virtual void Print() = 0;  
  23.   
  24. protected:  
  25.     char m_name[10];  
  26.     int m_age;  
  27. };  
  28.   
  29. class Stu: public People  
  30. {  
  31. public:  
  32.     Stu(const char* name, int age) : People(name, age)  
  33.     {  
  34.         printf("constructor Stu\n");  
  35.     }  
  36.     ~Stu()  
  37.     {  
  38.         printf("destructor Stu\n");  
  39.     }  
  40.   
  41. public:  
  42.     void Print()  
  43.     {  
  44.         printf("This is Stu Print, name: %s, age: %d\n", m_name, m_age);  
  45.     }  
  46. };  
  47.   
  48. class Worker : public People  
  49. {  
  50. public:  
  51.     Worker(const char* name, int age) : People(name, age)  
  52.     {  
  53.         printf("constructor worker\n");  
  54.     }  
  55.     ~Worker()  
  56.     {  
  57.         printf("destructor worker\n");  
  58.     }  
  59.   
  60. public:  
  61.     void Print()  
  62.     {  
  63.         printf("This is Worker Print, name: %s, age: %d\n", m_name, m_age);  
  64.     }  
  65. };  
  66.   
  67. void MapInsert()  
  68. {  
  69.     typedef map<string, shared_ptr<People> >::iterator Iterator;  
  70.     typedef pair<string, shared_ptr<People> > Pair;  
  71.     pair<string, int> stu_pair[3] = { make_pair("Peter", 10), make_pair("Rei", 14), make_pair("Kai", 16)};  
  72.     pair<string, int> wor_pair[3] = { make_pair("Jet", 20), make_pair("Piker", 24), make_pair("Ein", 26) };  
  73.     map<string, shared_ptr<People> > insert_map;  
  74.     for (int i = 0; i < 3; i++)  
  75.         pair<Iterator, bool> ret = insert_map.insert(Pair(stu_pair[i].first, make_shared<Stu>(stu_pair[i].first.c_str(), stu_pair[i].second)));  
  76.     for (int i = 0; i < 3; i++)  
  77.         pair<Iterator, bool> ret = insert_map.insert(Pair(wor_pair[i].first, make_shared<Worker>(wor_pair[i].first.c_str(), wor_pair[i].second)));  
  78.   
  79.     Iterator iter = insert_map.begin();  
  80.     for (; iter != insert_map.end(); iter++)  
  81.     {  
  82.         printf("%s: ", iter->first.c_str());  
  83.         iter->second->Print();  
  84.     }  
  85. }  
  86.   
  87. int _tmain(int argc, _TCHAR* argv[])  
  88. {  
  89.     MapInsert();  
  90.     getchar();  
  91.     return 0;  
  92. }  
运行结果如下:
  1. constructor Stu  
  2. constructor People  
  3. constructor worker  
  4. constructor People  
  5. constructor worker  
  6. constructor People  
  7. constructor worker  
  8. Ein: This is Worker Print, name: Ein, age: 26  
  9. Jet: This is Worker Print, name: Jet, age: 20  
  10. Kai: This is Stu Print, name: Kai, age: 16  
  11. Peter: This is Stu Print, name: Peter, age: 10  
  12. Piker: This is Worker Print, name: Piker, age: 24  
  13. Rei: This is Stu Print, name: Rei, age: 14  
  14. destructor Stu  
  15. destructor People  
  16. destructor worker  
  17. destructor People  
  18. destructor Stu  
  19. destructor People  
  20. destructor Stu  
  21. destructor People  
  22. destructor worker  
  23. destructor People  
  24. destructor worker  
  25. destructor People  

分析:map中插入不同于map指定的元素类别的时候,如果插入的类别可以转换成map允许插入的类别的话,map会帮你自动转换,如果不能转换则不能插入

map<int, int> imap;

imap.insert(pair<int, double>(10, 10.2))     //可以插入,但会损失精度

imap.insert(pair<double, char>(10.1, 'c'))  //可以插入,同样会损失精度

imap.insert(pair<int, string>(10, "s"))       //编译出错
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐