如何使用C++ STL map的insert()函数以四种不同方式高效插入数据?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2958个文字,预计阅读时间需要12分钟。
在STL的map模板类中,可以使用[]运算符进行重载,以实现根据不同使用场景的灵活操作。例如,可以通过重载[]运算符实现根据键值对元素进行查找、插入或更新等操作。以下是一个示例:
cpp#include #include
class MyMap {private: std::map data;
public: // 重载[]运算符 std::string& operator[](int key) { return data[key]; }
// 用于输出map的内容 void print() { for (const auto& pair : data) { std::cout << Key: < int main() { MyMap myMap; myMap[1]=one; myMap[2]=two; myMap[3]=three;
myMap.print();
return 0;}
在这个示例中,我们定义了一个名为`MyMap`的类,它内部包含一个`std::map`。我们重载了`[]`运算符,使其能够直接通过键值对来访问或修改map中的元素。在`main`函数中,我们创建了一个`MyMap`对象,并使用`[]`运算符添加了三个键值对,然后通过`print`函数打印出map的内容。
前面讲过,C++ STL map 类模板中对[ ]运算符进行了重载,即根据使用场景的不同,借助[ ]运算符可以实现不同的操作。举个例子:
#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { std::map<string, string> mymap{ {"STL教程","c.biancheng.net/java/"} }; //获取已存储键值对中,指定键对应的值 cout << mymap["STL教程"] << endl; //向 map 容器添加新键值对 mymap["Python教程"] = "c.biancheng.net/python/"; //修改 map 容器已存储键值对中,指定键对应的值 mymap["STL教程"] = "c.biancheng.net/stl/"; for (auto iter = mymap.begin(); iter != mymap.end(); ++iter) { cout << iter->first << " " << iter->second << endl; } return 0; } 程序执行结果为:
c.biancheng.net/java/
Python教程 c.biancheng.net/python/
STL教程 c.biancheng.net/stl/
实际上,除了使用 [ ] 运算符实现向 map 容器中添加新键值对外,map 类模板中还提供有 insert() 成员方法,该方法专门用来向 map 容器中插入新的键值对。
注意,这里所谓的“插入”,指的是 insert() 方法可以将新的键值对插入到 map 容器中的指定位置,但这与 map 容器会自动对存储的键值对进行排序并不冲突。当使用 insert() 方法向 map 容器的指定位置插入新键值对时,其底层会先将新键值对插入到容器的指定位置,如果其破坏了 map 容器的有序性,该容器会对新键值对的位置进行调整。
自 C++ 11 标准后,insert() 成员方法的用法大致有以下 4 种。1) 无需指定插入位置,直接将键值对添加到 map 容器中。insert() 方法的语法格式有以下 2 种:
//1、引用传递一个键值对
pair<iterator,bool> insert (const value_type& val);
//2、以右值引用的方式传递键值对
template <class P>
pair<iterator,bool> insert (P&& val);
- 如果成功插入 val,则该迭代器指向新插入的 val,bool 值为 true;
- 如果插入 val 失败,则表明当前 map 容器中存有和 val 的键相同的键值对(用 p 表示),此时返回的迭代器指向 p,bool 值为 false。
以上 2 种语法格式的区别在于传递参数的方式不同,即无论是局部定义的键值对变量还是全局定义的键值对变量,都采用普通引用传递的方式;而对于临时的键值对变量,则以右值引用的方式传参。有关右值引用,可阅读《C++右值引用》一文做详细了解。
举个例子:#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { //创建一个空 map 容器 std::map<string, string> mymap; //创建一个真实存在的键值对变量 std::pair<string, string> STL = { "STL教程","c.biancheng.net/stl/" }; //创建一个接收 insert() 方法返回值的 pair 对象 std::pair<std::map<string, string>::iterator, bool> ret; //插入 STL,由于 STL 并不是临时变量,因此会以第一种方式传参 ret = mymap.insert(STL); cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl; //以右值引用的方式传递临时的键值对变量 ret = mymap.insert({ "C语言教程","c.biancheng.net/c/" }); cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl; //插入失败样例 ret = mymap.insert({ "STL教程","c.biancheng.net/java/" }); cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl; return 0; } 程序执行结果为:
ret.iter = <{STL教程, c.biancheng.net/stl/}, 1>
ret.iter = <{C语言教程, c.biancheng.net/c/}, 1>
ret.iter = <{STL教程, c.biancheng.net/stl/}, 0>
- 对于插入成功的 insert() 方法,其返回的 pair 对象中包含一个指向新插入键值对的迭代器和值为 1 的 bool 变量
- 对于插入失败的 insert() 方法,同样会返回一个 pair 对象,其中包含一个指向 map 容器中键为 "STL教程" 的键值对和值为 0 的 bool 变量。
另外,在程序中的第 21 行代码,还可以使用如下 2 种方式创建临时的键值对变量,它们是等价的:
//调用 pair 类模板的构造函数
ret = mymap.insert(pair<string,string>{ "C语言教程","c.biancheng.net/c/" });
//调用 make_pair() 函数
ret = mymap.insert(make_pair("C语言教程", "c.biancheng.net/c/"));
2) 除此之外,insert() 方法还支持向 map 容器的指定位置插入新键值对,该方法的语法格式如下:
//以普通引用的方式传递 val 参数
iterator insert (const_iterator position, const value_type& val);
//以右值引用的方式传递 val 键值对参数
template <class P>
iterator insert (const_iterator position, P&& val);
- 如果插入成功,insert() 方法会返回一个指向 map 容器中已插入键值对的迭代器;
- 如果插入失败,insert() 方法同样会返回一个迭代器,该迭代器指向 map 容器中和 val 具有相同键的那个键值对。
举个例子:
#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { //创建一个空 map 容器 std::map<string, string> mymap; //创建一个真实存在的键值对变量 std::pair<string, string> STL = { "STL教程","c.biancheng.net/stl/" }; //指定要插入的位置 std::map<string, string>::iterator it = mymap.begin(); //向 it 位置以普通引用的方式插入 STL auto iter1 = mymap.insert(it, STL); cout << iter1->first << " " << iter1->second << endl; //向 it 位置以右值引用的方式插入临时键值对 auto iter2 = mymap.insert(it, std::pair<string, string>("C语言教程", "c.biancheng.net/c/")); cout << iter2->first << " " << iter2->second << endl; //插入失败样例 auto iter3 = mymap.insert(it, std::pair<string, string>("STL教程", "c.biancheng.net/java/")); cout << iter3->first << " " << iter3->second << endl; return 0; } 程序执行结果为:
STL教程 c.biancheng.net/stl/
C语言教程 c.biancheng.net/c/
STL教程 c.biancheng.net/stl/
再次强调,即便指定了新键值对的插入位置,map 容器仍会对存储的键值对进行排序。也可以说,决定新插入键值对位于 map 容器中位置的,不是 insert() 方法中传入的迭代器,而是新键值对中键的值。
3) insert() 方法还支持向当前 map 容器中插入其它 map 容器指定区域内的所有键值对,该方法的语法格式如下:
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
<first,last>可以表示某 map 容器中的指定区域。举个例子:
#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { //创建并初始化 map 容器 std::map<std::string, std::string>mymap{ {"STL教程","c.biancheng.net/stl/"}, {"C语言教程","c.biancheng.net/c/"}, {"Java教程","c.biancheng.net/java/"} }; //创建一个空 map 容器 std::map<std::string, std::string>copymap; //指定插入区域 std::map<string, string>::iterator first = ++mymap.begin(); std::map<string, string>::iterator last = mymap.end(); //将<first,last>区域内的键值对插入到 copymap 中 copymap.insert(first, last); //遍历输出 copymap 容器中的键值对 for (auto iter = copymap.begin(); iter != copymap.end(); ++iter) { cout << iter->first << " " << iter->second << endl; } return 0; } 程序执行结果为:
Java教程 c.biancheng.net/java/
STL教程 c.biancheng.net/stl/
4) 除了以上一种格式外,insert() 方法还允许一次向 map 容器中插入多个键值对,其语法格式为:
void insert ({val1, val2, ...});
其中,vali都表示的是键值对变量。举个例子:
#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { //创建空的 map 容器 std::map<std::string, std::string>mymap; //向 mymap 容器中添加 3 个键值对 mymap.insert({ {"STL教程", "c.biancheng.net/stl/"}, { "C语言教程","c.biancheng.net/c/" }, { "Java教程","c.biancheng.net/java/" } }); for (auto iter = mymap.begin(); iter != mymap.end(); ++iter) { cout << iter->first << " " << iter->second << endl; } return 0; } 程序执行结果为:
C语言教程 c.biancheng.net/c/
Java教程 c.biancheng.net/java/
STL教程 c.biancheng.net/stl/
值得一提的是,除了 insert() 方法,map 类模板还提供 emplace() 和 emplace_hint() 方法,它们也可以完成向 map 容器中插入键值对的操作,且效率还会 insert() 方法高。关于这 2 个方法,会在下一节做详细介绍。
本文共计2958个文字,预计阅读时间需要12分钟。
在STL的map模板类中,可以使用[]运算符进行重载,以实现根据不同使用场景的灵活操作。例如,可以通过重载[]运算符实现根据键值对元素进行查找、插入或更新等操作。以下是一个示例:
cpp#include #include
class MyMap {private: std::map data;
public: // 重载[]运算符 std::string& operator[](int key) { return data[key]; }
// 用于输出map的内容 void print() { for (const auto& pair : data) { std::cout << Key: < int main() { MyMap myMap; myMap[1]=one; myMap[2]=two; myMap[3]=three;
myMap.print();
return 0;}
在这个示例中,我们定义了一个名为`MyMap`的类,它内部包含一个`std::map`。我们重载了`[]`运算符,使其能够直接通过键值对来访问或修改map中的元素。在`main`函数中,我们创建了一个`MyMap`对象,并使用`[]`运算符添加了三个键值对,然后通过`print`函数打印出map的内容。
前面讲过,C++ STL map 类模板中对[ ]运算符进行了重载,即根据使用场景的不同,借助[ ]运算符可以实现不同的操作。举个例子:
#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { std::map<string, string> mymap{ {"STL教程","c.biancheng.net/java/"} }; //获取已存储键值对中,指定键对应的值 cout << mymap["STL教程"] << endl; //向 map 容器添加新键值对 mymap["Python教程"] = "c.biancheng.net/python/"; //修改 map 容器已存储键值对中,指定键对应的值 mymap["STL教程"] = "c.biancheng.net/stl/"; for (auto iter = mymap.begin(); iter != mymap.end(); ++iter) { cout << iter->first << " " << iter->second << endl; } return 0; } 程序执行结果为:
c.biancheng.net/java/
Python教程 c.biancheng.net/python/
STL教程 c.biancheng.net/stl/
实际上,除了使用 [ ] 运算符实现向 map 容器中添加新键值对外,map 类模板中还提供有 insert() 成员方法,该方法专门用来向 map 容器中插入新的键值对。
注意,这里所谓的“插入”,指的是 insert() 方法可以将新的键值对插入到 map 容器中的指定位置,但这与 map 容器会自动对存储的键值对进行排序并不冲突。当使用 insert() 方法向 map 容器的指定位置插入新键值对时,其底层会先将新键值对插入到容器的指定位置,如果其破坏了 map 容器的有序性,该容器会对新键值对的位置进行调整。
自 C++ 11 标准后,insert() 成员方法的用法大致有以下 4 种。1) 无需指定插入位置,直接将键值对添加到 map 容器中。insert() 方法的语法格式有以下 2 种:
//1、引用传递一个键值对
pair<iterator,bool> insert (const value_type& val);
//2、以右值引用的方式传递键值对
template <class P>
pair<iterator,bool> insert (P&& val);
- 如果成功插入 val,则该迭代器指向新插入的 val,bool 值为 true;
- 如果插入 val 失败,则表明当前 map 容器中存有和 val 的键相同的键值对(用 p 表示),此时返回的迭代器指向 p,bool 值为 false。
以上 2 种语法格式的区别在于传递参数的方式不同,即无论是局部定义的键值对变量还是全局定义的键值对变量,都采用普通引用传递的方式;而对于临时的键值对变量,则以右值引用的方式传参。有关右值引用,可阅读《C++右值引用》一文做详细了解。
举个例子:#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { //创建一个空 map 容器 std::map<string, string> mymap; //创建一个真实存在的键值对变量 std::pair<string, string> STL = { "STL教程","c.biancheng.net/stl/" }; //创建一个接收 insert() 方法返回值的 pair 对象 std::pair<std::map<string, string>::iterator, bool> ret; //插入 STL,由于 STL 并不是临时变量,因此会以第一种方式传参 ret = mymap.insert(STL); cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl; //以右值引用的方式传递临时的键值对变量 ret = mymap.insert({ "C语言教程","c.biancheng.net/c/" }); cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl; //插入失败样例 ret = mymap.insert({ "STL教程","c.biancheng.net/java/" }); cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl; return 0; } 程序执行结果为:
ret.iter = <{STL教程, c.biancheng.net/stl/}, 1>
ret.iter = <{C语言教程, c.biancheng.net/c/}, 1>
ret.iter = <{STL教程, c.biancheng.net/stl/}, 0>
- 对于插入成功的 insert() 方法,其返回的 pair 对象中包含一个指向新插入键值对的迭代器和值为 1 的 bool 变量
- 对于插入失败的 insert() 方法,同样会返回一个 pair 对象,其中包含一个指向 map 容器中键为 "STL教程" 的键值对和值为 0 的 bool 变量。
另外,在程序中的第 21 行代码,还可以使用如下 2 种方式创建临时的键值对变量,它们是等价的:
//调用 pair 类模板的构造函数
ret = mymap.insert(pair<string,string>{ "C语言教程","c.biancheng.net/c/" });
//调用 make_pair() 函数
ret = mymap.insert(make_pair("C语言教程", "c.biancheng.net/c/"));
2) 除此之外,insert() 方法还支持向 map 容器的指定位置插入新键值对,该方法的语法格式如下:
//以普通引用的方式传递 val 参数
iterator insert (const_iterator position, const value_type& val);
//以右值引用的方式传递 val 键值对参数
template <class P>
iterator insert (const_iterator position, P&& val);
- 如果插入成功,insert() 方法会返回一个指向 map 容器中已插入键值对的迭代器;
- 如果插入失败,insert() 方法同样会返回一个迭代器,该迭代器指向 map 容器中和 val 具有相同键的那个键值对。
举个例子:
#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { //创建一个空 map 容器 std::map<string, string> mymap; //创建一个真实存在的键值对变量 std::pair<string, string> STL = { "STL教程","c.biancheng.net/stl/" }; //指定要插入的位置 std::map<string, string>::iterator it = mymap.begin(); //向 it 位置以普通引用的方式插入 STL auto iter1 = mymap.insert(it, STL); cout << iter1->first << " " << iter1->second << endl; //向 it 位置以右值引用的方式插入临时键值对 auto iter2 = mymap.insert(it, std::pair<string, string>("C语言教程", "c.biancheng.net/c/")); cout << iter2->first << " " << iter2->second << endl; //插入失败样例 auto iter3 = mymap.insert(it, std::pair<string, string>("STL教程", "c.biancheng.net/java/")); cout << iter3->first << " " << iter3->second << endl; return 0; } 程序执行结果为:
STL教程 c.biancheng.net/stl/
C语言教程 c.biancheng.net/c/
STL教程 c.biancheng.net/stl/
再次强调,即便指定了新键值对的插入位置,map 容器仍会对存储的键值对进行排序。也可以说,决定新插入键值对位于 map 容器中位置的,不是 insert() 方法中传入的迭代器,而是新键值对中键的值。
3) insert() 方法还支持向当前 map 容器中插入其它 map 容器指定区域内的所有键值对,该方法的语法格式如下:
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
<first,last>可以表示某 map 容器中的指定区域。举个例子:
#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { //创建并初始化 map 容器 std::map<std::string, std::string>mymap{ {"STL教程","c.biancheng.net/stl/"}, {"C语言教程","c.biancheng.net/c/"}, {"Java教程","c.biancheng.net/java/"} }; //创建一个空 map 容器 std::map<std::string, std::string>copymap; //指定插入区域 std::map<string, string>::iterator first = ++mymap.begin(); std::map<string, string>::iterator last = mymap.end(); //将<first,last>区域内的键值对插入到 copymap 中 copymap.insert(first, last); //遍历输出 copymap 容器中的键值对 for (auto iter = copymap.begin(); iter != copymap.end(); ++iter) { cout << iter->first << " " << iter->second << endl; } return 0; } 程序执行结果为:
Java教程 c.biancheng.net/java/
STL教程 c.biancheng.net/stl/
4) 除了以上一种格式外,insert() 方法还允许一次向 map 容器中插入多个键值对,其语法格式为:
void insert ({val1, val2, ...});
其中,vali都表示的是键值对变量。举个例子:
#include <iostream> #include <map> //map #include <string> //string using namespace std; int main() { //创建空的 map 容器 std::map<std::string, std::string>mymap; //向 mymap 容器中添加 3 个键值对 mymap.insert({ {"STL教程", "c.biancheng.net/stl/"}, { "C语言教程","c.biancheng.net/c/" }, { "Java教程","c.biancheng.net/java/" } }); for (auto iter = mymap.begin(); iter != mymap.end(); ++iter) { cout << iter->first << " " << iter->second << endl; } return 0; } 程序执行结果为:
C语言教程 c.biancheng.net/c/
Java教程 c.biancheng.net/java/
STL教程 c.biancheng.net/stl/
值得一提的是,除了 insert() 方法,map 类模板还提供 emplace() 和 emplace_hint() 方法,它们也可以完成向 map 容器中插入键值对的操作,且效率还会 insert() 方法高。关于这 2 个方法,会在下一节做详细介绍。

