C++ STL map插入数据

一、前言

前面已经说过,可以通过[]运算符修改或者添加键值对,在这里就不说这种用法了。

二、方法

1、insert

insert方法是专门用来向 map 容器中插入新的键值对的。这里的"插入"指的是 insert() 方法可以将新的键值对插入到 map 容器中的指定位置。如果破坏了map容器的有序性,map容器会对新键值对的位置进行调整,也就是说,虽然insert可以将键值对插入指定的位置,但是插入之后map容器会检查插入的键值对是否符合有序性,不符合的话insert指定的位置就不是插入键值对真正的位置了。

1)不指定位置,直接插入

格式说明
pair<iterator,bool> insert (const value_type& val);引用传递一个键值对
template <class P> pair<iterator,bool> insert (P&& val);以右值引用的方式传递键值对

区别:传递参数的方式不同。无论是局部定义的键值对变量还是全局定义的键值对变量,都采用普通引用传递的方式;而对于临时的键值对变量,则以右值引用的方式传参。

std::map<int, string> mapInfo{ {1,"test"},{2,"lin"},{3,"wei"} };

//格式1
std::pair<int, string> mapData = { 4, "wu" };
std::pair<std::map<int, string>::iterator, bool> ret;
ret = mapInfo.insert(mapData);
std::cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << std::endl;

//格式2
ret = mapInfo.insert({ 5,"ouyang" });
//等价于
//ret = mapInfo.insert(pair<int, string>{5, "ouyang"});
//ret = mapInfo.insert(make_pair(5, "ouyang"));
std::cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << std::endl;

//插入失败
ret = mapInfo.insert({ 1,"lu" });
std::cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << std::endl;
    
std::map<int, string>::iterator mapIter = mapInfo.begin();
for (; mapIter != mapInfo.end(); mapIter++)
{
    std::cout << mapIter->first << "  " << mapIter->second << std::endl;
}
   

结果如下:
image.png
由结果可知:
①返回值是一个 pair 对象,其中 pair.first 表示一个迭代器,pair.second 为一个 bool 类型变量:
如果成功插入 val,则该迭代器指向新插入的 val,bool 值为 true;
如果插入 val 失败,则表明当前 map 容器中存有和 val 的键相同的键值对(用 p 表示),此时返回的迭代器指向 p,bool 值为 false。

2)指定位置插入

格式说明
iterator insert (const_iterator position, const value_type& val);以普通引用的方式传递 val 参数
template <class P> iterator insert (const_iterator position, P&& val);以右值引用的方式传递 val 键值对参数
std::map<int, string> mapInfo{ {1,"test"},{2,"lin"},{3,"wei"} };

//格式1
std::pair<int, string> mapData = { 4, "wu" };
std::map<int, string>::iterator mapIter = mapInfo.begin();
std::map<int, string>::iterator insertIter = mapInfo.insert(++mapIter, mapData);
std::cout << insertIter->first << "  " << insertIter->second << std::endl;

//格式2
insertIter = mapInfo.insert(++mapIter, std::pair<int, string>(5, "kai"));
std::cout << insertIter->first << "  " << insertIter->second << std::endl;

//插入失败
insertIter = mapInfo.insert(++mapIter, std::pair<int,string>(3,"ouyang"));
std::cout << insertIter->first << "  " << insertIter->second << std::endl;

mapIter = mapInfo.begin();
for (; mapIter != mapInfo.end(); mapIter++)
{
    std::cout << mapIter->first << "  " << mapIter->second << std::endl;
}

结果如下:
image.png
由结果可知:
①和不指定位置的插入的方法的区别,这里返回的是迭代器
如果插入成功,insert() 方法会返回一个指向 map 容器中已插入键值对的迭代器;
如果插入失败,insert() 方法同样会返回一个迭代器,该迭代器指向 map 容器中和 val 具有相同键的那个键值对。

3)向当前 map 容器中插入其它 map 容器指定区域内的所有键值对

格式
template <class InputIterator> void insert (InputIterator first, InputIterator last);
std::map<int, string> mapInfo{ {1,"test"},{2,"lin"},{3,"wei"} };
std::map<int, string> mapInfo2;

std::map<int, string>::iterator first = ++mapInfo.begin();
std::map<int, string>::iterator last = mapInfo.end();
   
mapInfo2.insert(first, last);

std::map<int, string>::iterator mapIter = mapInfo2.begin();
for (; mapIter != mapInfo2.end(); mapIter++)
{
    std::cout << mapIter->first << "  " << mapIter->second << std::endl;
}
   

结果如下:
image.png
由结果可知:
①需要其他map容器的开始和结束的迭代器,组成一个指定区域

4)一次向 map 容器中插入多个键值对

表列 A
void insert ({val1, val2, ...});
std::map<int, string> mapInfo;
mapInfo.insert({ {1,"test"},{2,"lin"},{3,"wei"} });

std::map<int, string>::iterator mapIter = mapInfo.begin();
for (; mapIter != mapInfo.end(); mapIter++)
{
    std::cout << mapIter->first << "  " << mapIter->second << std::endl;
}

结果如下:
image.png

insert的介绍就到这里,接下来讲讲比insert高效的方法

2、emplace

| 表列 A |
| ----- |
| template <class... Args> pair<iterator,bool> emplace (Args&&... args); |

std::map<int, string> mapInfo;
pair<map<int, string>::iterator, bool> ret = mapInfo.emplace(1, "test");
std::cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << std::endl;
    
ret = mapInfo.emplace(2, "lin");
std::cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << std::endl;

ret = mapInfo.emplace(2, "kai");
std::cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << std::endl;
std::map<int, string>::iterator mapIter = mapInfo.begin();
for (; mapIter != mapInfo.end(); mapIter++)
{
    std::cout << mapIter->first << "  " << mapIter->second << std::endl;
}

结果如下:
image.png
由结果可知:
①使用emplace方法时,将创建新键值对所需的数据作为参数直接传入即可,返回值是一个pair对象,和不指定位置的insert方法的返回值一样

3、emplace_hint

格式
template <class... Args> iterator emplace_hint (const_iterator position, Args&&... args);

该方法不仅要传入创建键值对所需要的数据,还需要传入一个迭代器作为第一个参数,指明要插入的位置。

std::map<int, string> mapInfo;
map<int, string>::iterator iter = mapInfo.emplace_hint(mapInfo.begin(), 1, "test");
std::cout << iter->first << "  " << iter->second << std::endl;

iter = mapInfo.emplace_hint(mapInfo.begin(), 2, "lin");
cout << iter->first << " " << iter->second << endl;

iter = mapInfo.emplace_hint(mapInfo.begin(), 2, "kai");
cout << "insert 2 kai  finial " << iter->first << " " << iter->second << endl;
std::map<int, string>::iterator mapIter = mapInfo.begin();
for (; mapIter != mapInfo.end(); mapIter++)
{
    std::cout << mapIter->first << "  " << mapIter->second << std::endl;
}

结果如下:
image.png
①返回值是一个迭代器。当成功插入新键值对时,返回的迭代器指向新插入的键值对;反之,如果插入失败,则表明 map 容器中存有相同键的键值对,返回的迭代器就指向这个键值对

小菜鸟一枚,望各位大佬不吝指教,用于记录学习

1 声望
0 粉丝
0 条评论
推荐阅读
C++ STL multiset容器
multiset 类模板提供的构造函数,和 set 类模板中提供创建 set 容器的构造函数,是完全相同的。因此创建set容器的方式适用于创建multiset容器。具体的方法参考set容器:[链接]

等待樱花盛开阅读 970

年度最佳【golang】sync.Map详解
工作中,经常会碰到并发读写 map 而造成 panic 的情况,为什么在并发读写的时候,会 panic 呢?因为在并发读写的情况下,map 里的数据会被写乱,之后就是 Garbage in, garbage out,还不如直接 panic 了。

去去10024阅读 7.2k

万字避坑指南!C++的缺陷与思考(上)
导语 | 本文主要总结了本人在C++开发过程中对一些奇怪、复杂的语法的理解和思考,同时作为C++开发的避坑指南。前言C++是一门古老的语言,但仍然在不间断更新中,不断引用新特性。但与此同时C++又甩不掉巨大的历史...

腾讯云开发者6阅读 517

麒麟操作系统 (kylinos) 从入门到精通 - 研发环境 - 第二十一篇 C++/C语言开发环境搭建
类别:笔记本型号:中国长城 NF14C硬件平台:飞腾处理器(ArmV8 指令集)系统:银河麒麟操作系统 V10 SP1(2203) 关键词:信创,麒麟系统,linux,c++,c,内核飞腾,arm

码上世界1阅读 2.3k评论 1

封面图
万字避坑指南!C++的缺陷与思考(下)
导读 | 在万字避坑指南!C++的缺陷与思考(上)一文中,微信后台开发工程师胡博豪,分享了C++的发展历史、右值引用与移动语义、类型说明符等内容,深受广大开发者喜爱!此篇,我们邀请作者继续总结其在C++开发过...

腾讯云开发者5阅读 484评论 1

一种将函数模板定义和声明分开的方法
&emsp;&emsp;在 C++ 中为了操作简洁引入了函数模板。所谓的函数模板实际上是建立一个通用函数,其函数类型或形参类型不具体指定,用一个虚拟的类型来表达,这个通用函数就称为函数模板。

Sharemaker阅读 864

封面图
Workflow的JSON解析器
Workflow中有一个小而美的json-parser,一千行代码写得非常典雅精致。不仅可以学习到经典的C语言写法、递归解析的架构、与内核近似的编码风格、简洁的接口设计,而且也非常方便引入项目中作为轻量级的json解析器...

1412阅读 812

小菜鸟一枚,望各位大佬不吝指教,用于记录学习

1 声望
0 粉丝
宣传栏