C++STL容器 – std::map容器修改、元素操作总结 clear,insert,emplace,erase,swap,merge,extract,insert_or_assign等
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:C++STL容器 – std::map容器修改、元素操作总结 clear,insert,emplace,erase,swap,merge,extract,insert_or_assign等
原文链接:https://www.stubbornhuang.com/1992/
发布于:2022年03月01日 14:19:04
修改于:2022年03月01日 14:19:04

std::map是一个排序的关联容器,具有唯一键值特性。其实现底层数据结构为红黑树。在红黑树上的查找、插入、删除操作的算法复杂度为O(logN)。本文将对std::map的有关容器修改的函数进行说明和总结。
1 std::map常见函数
1.1 std::map容器修改操作函数
1.1.1 clear
clear的作用主要是清除std::map中的所有元素。
#include <iostream>
#include <map>
#include <string>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.clear();
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
1.1.2 insert
insert的作用主要是向std::map容器中插入元素。
如果容器中未包含插入数据对的键值,则将数据对插入容器中;如果容器中已包含插入数据对的键值,则不将数据对插入容器中。具体区别可查看以下代码:
#include <iostream>
#include <map>
#include <string>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.insert({1,"2"});
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.insert({ 6,"6" });
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
2 2
3 3
4 4
6 6
我们在向容器中插入元素时可以使用以下方式:
- 初始化列表
- std::pair
- std::make_pair
- 根据迭代器位置插入
- 其他高级方式,如左值,右值等
通过初始化列表插入
myMap.insert({1,"2"});
myMap.insert({ {1,"a"},{2,"b"} });
通过std::pair插入
myMap.insert(std::pair<int,std::string>(1,"a"));
通过std::make_pair插入
myMap.insert(std::make_pair(1,"a"));
在容器迭代器指定的位置插入
myMap.insert(myMap.begin(), std::make_pair(6,"a"));
1.1.3 insert_or_assign(C++17)
insert_or_assign作用主要是向std::map容器中插入元素,元素是就地构造的,即不执行赋值和移动操作。
insert_or_assign与上述的insert函数不同的是,如果容器中存在于插入数据对相同的键值,则将数据对的值赋值给容器中响应的键值对,覆盖原有键值对中的值;如果容器中不存在插入数据对相同的键值,则插入新的数据对,作用与insert函数一样。
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.insert_or_assign(1, "a");
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 a
2 2
3 3
4 4
1.1.4 emplace(C++11)
emplace函数主要作用是如果容器中没有相同键的元素,则将新元素就地构造插入到容器中。
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.emplace(6, "a");
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
2 2
3 3
4 4
6 a
也可通过以下方式进行插入:
- std::pair
- std::make_pair
使用std::pair进行emplace
myMap.emplace(std::pair<int,std::string>(6,"a"));
使用std::make_pair进行emplace
myMap.emplace(std::make_pair(6,"a"));
1.1.5 emplace_hint(C++11)
1.1.6 try_emplace(C++17)
try_emplace函数主要作用是如果容器中没有相同键的元素,则将新元素插入到容器中,其新元素使用给定的args构造。
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.try_emplace(6,"a");
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
myMap.try_emplace(6, "b");
PrintMap(myMap);
return 0;
}
结果:
original map
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
2 2
3 3
4 4
6 a
modifed map:
0 0
1 1
2 2
3 3
4 4
6 a
1.1.7 erase
erase函数的作用主要是从std::map中移除指定的元素。
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
void PrintMap(const std::map<int, std::string>& inMap)
{
std::map<int, std::string>::const_iterator const_iter = inMap.begin();
while (const_iter != inMap.end())
{
std::cout << const_iter->first << " " << const_iter->second << std::endl;
const_iter++;
}
}
int main()
{
std::cout << "original map:" << std::endl;
std::map<int, std::string> myMap;
for (int i = 0; i < 5; ++i)
{
myMap[i] = std::to_string(i);
}
PrintMap(myMap);
std::cout << "modifed map:" << std::endl;
for (auto iter = myMap.begin(); iter != myMap.end();)
{
if (iter->first == 2)
{
iter = myMap.erase(iter);
}
else
{
iter++;
}
}
PrintMap(myMap);
return 0;
}
结果:
original map:
0 0
1 1
2 2
3 3
4 4
modifed map:
0 0
1 1
3 3
4 4
1.1.8 swap
swap函数的作用主要是与其它容器的内容进行对换。
#include <iostream>
#include <string>
#include <utility>
#include <map>
// print out a std::pair
template <class Os, class U, class V>
Os& operator<<(Os& os, const std::pair<U, V>& p) {
return os << p.first << ":" << p.second;
}
// print out a container
template <class Os, class Co>
Os& operator<<(Os& os, const Co& co) {
os << "{";
for (auto const& i : co) { os << ' ' << i; }
return os << " }\n";
}
int main()
{
std::map<std::string, std::string>
m1 { {"γ", "gamma"}, {"β", "beta"}, {"α", "alpha"}, {"γ", "gamma"}, },
m2 { {"ε", "epsilon"}, {"δ", "delta"}, {"ε", "epsilon"} };
const auto& ref = *(m1.begin());
const auto iter = std::next(m1.cbegin());
std::cout << "──────── before swap ────────\n"
<< "m1: " << m1 << "m2: " << m2 << "ref: " << ref
<< "\niter: " << *iter << '\n';
m1.swap(m2);
std::cout << "──────── after swap ────────\n"
<< "m1: " << m1 << "m2: " << m2 << "ref: " << ref
<< "\niter: " << *iter << '\n';
// Note that every iterator referring to an element in one container before
// the swap refers to the same element in the other container after the swap.
// Same is true for references.
}
结果:
──────── before swap ────────
m1: { α:alpha β:beta γ:gamma }
m2: { δ:delta ε:epsilon }
ref: α:alpha
iter: β:beta
──────── after swap ────────
m1: { δ:delta ε:epsilon }
m2: { α:alpha β:beta γ:gamma }
ref: α:alpha
iter: β:beta
1.1.9 extract(C++17)
extract函数的作用主要是将给定位置或者给定键值的元素节点取消在当前容器中的链接,并返回该元素的节点句柄。如果没有给定键值的元素,则返回空的节点句柄。此操作不会复制或者拷贝元素,只是重新调整容器内部的节点指针指向。extract函数只会使得当前提取的元素的迭代器无效,提取元素的指针和引用仍然有效,但在元素由节点句柄拥有时不能使用:如果元素被插入容器,它们将变得可用。
#include <algorithm>
#include <iostream>
#include <map>
int main()
{
std::map<int, char> cont{{1, 'a'}, {2, 'b'}, {3, 'c'}};
auto print = [](std::pair<const int, char>& n) {
std::cout << " " << n.first << '(' << n.second << ')';
};
std::cout << "Start:";
std::for_each(cont.begin(), cont.end(), print);
std::cout << '\n';
// Extract node handle and change key
auto nh = cont.extract(1);
nh.key() = 4;
std::cout << "After extract and before insert:";
std::for_each(cont.begin(), cont.end(), print);
std::cout << '\n';
// Insert node handle back
cont.insert(move(nh));
std::cout << "End:";
std::for_each(cont.begin(), cont.end(), print);
std::cout << '\n';
}
结果:
Start: 1(a) 2(b) 3(c)
After extract and before insert: 2(b) 3(c)
End: 2(b) 3(c) 4(a)
1.1.10 merge(C++17)
merge函数的作用主要是将输入容器的所有元素重新合并到当前容器中,如果输入容器中有与当前容器键值相同元素,则不进行合并。在这一过程中没有元素拷贝和移动操作,只是要合并的元素从输入容器指向当前容器。
#include <map>
#include <iostream>
#include <string>
int main()
{
std::map<int, std::string> ma {{1, "apple"}, {5, "pear"}, {10, "banana"}};
std::map<int, std::string> mb {{2, "zorro"}, {4, "batman"}, {5, "X"}, {8, "alpaca"}};
std::map<int, std::string> u;
u.merge(ma);
std::cout << "ma.size(): " << ma.size() << '\n';
u.merge(mb);
std::cout << "mb.size(): " << mb.size() << '\n';
std::cout << "mb.at(5): " << mb.at(5) << '\n';
for(auto const &kv: u)
std::cout << kv.first << ", " << kv.second << '\n';
}
结果:
ma.size(): 0
mb.size(): 1
mb.at(5): X
1, apple
2, zorro
4, batman
5, pear
8, alpaca
10, banana
当前分类随机文章推荐
- C++11 - override关键字简要介绍 阅读1920次,点赞0次
- C++ - Map中存储动态指针时正确释放内存 阅读3473次,点赞0次
- C++11 - std::shared_ptr初始化的几种方式 阅读6644次,点赞2次
- C++11 - 基于无锁队列的单生产者单消费者模型 阅读5390次,点赞1次
- C++ - 左值和右值,右值引用与移动语义的概念与理解 阅读137次,点赞1次
- C++11/std::thread - 线程的基本用法 阅读3084次,点赞0次
- C++11/std::atomic - 原子变量(不加锁实现线程互斥) 阅读5851次,点赞2次
- C++ – UTF8编码下的全角字符转半角字符 阅读1421次,点赞0次
- C++ - 使用宏区分不同系统平台、不同编译器、不同编译模式等编译期宏使用总结 阅读1107次,点赞0次
- C++ - 随机洗牌算法,std::random_shuffle和std::shuffle 阅读1071次,点赞1次
全站随机文章推荐
- 资源分享 - Handbook of Digital Image Synthesis - Scientific Foundations of Rendering 英文高清PDF下载 阅读1098次,点赞0次
- 资源分享 - Vulkan Programming Guide - The Official Guide to Learning Vulkan 英文高清PDF下载 阅读2412次,点赞0次
- FFmpeg - 常用的视频像素格式以及使用SwsContext和sws_scale进行视频像素格式转换和视频缩放 阅读625次,点赞0次
- 资源分享 - Behavioral Mathematics for Game AI 英文高清PDF下载 阅读767次,点赞0次
- Alphapose - Windows下Alphapose(Pytorch 1.1+)版本2021最新环境配置步骤以及踩坑说明 阅读4407次,点赞1次
- OpenCV - 打开视频文件,并对其中的每一帧图像进行Canny算子边缘化提取,并将结果保存为视频文件 阅读2791次,点赞0次
- FFmpeg - 自定义http请求参数,如user-agent,headers,referer等 阅读309次,点赞0次
- 书籍翻译 – Fundamentals of Computer Graphics, Fourth Edition,第10章 Surface Shading中文翻译 阅读1247次,点赞3次
- 资源分享 - Computer Graphics, C Version , Second Edition 英文高清PDF下载 阅读831次,点赞0次
- C++ – 字节数组byte[]或者unsigned char[]与bool的相互转换 阅读772次,点赞1次
评论
164