作为关联式容器的一种,map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。其中,各个键值对的键和值可以是任意数据类型,包括C++ 基本数据类型(int、double 等)、使用结构体或类自定义的类型。
在使用 map 容器存储多个键值对时,该容器会自动根据各键值对的键的大小,按照既定的规则进行排序。默认情况下,map 容器选用std::less<T>
排序规则(其中 T 表示键的数据类型),其会根据键的大小对所有键值对做升序排序。当然,根据实际情况的需要,我们可以手动指定 map 容器的排序规则,既可以选用 STL 标准库中提供的其它排序规则(比如std::greater<T>
),也可以自定义排序规则。
另外需要注意的是,使用 map 容器存储的各个键值对,键的值既不能重复也不能被修改。换句话说,map 容器中存储的各个键值对不仅键的值独一无二,键的类型也会用 const 修饰,这意味着只要键值对被存储到 map 容器中,其键的值将不能再做任何修改。
map 容器存储的都是 pair 类型的键值对元素,更确切的说,该容器存储的都是 pair<const K, T> 类型(其中 K 和 T 分别表示键和值的数据类型)的键值对元素。
本文作者原创,转载请附上文章出处与本文链接。
C++ STL map容器(深入了解,一文学会)目录
10 operator[]和insert() 如何选择与效率对比
1 map容器的成员函数
成员方法 | 功能 |
---|---|
begin() | 返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
end() | 返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
rbegin() | 返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。 |
rend() | 返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。 |
cbegin() | 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。 |
cend() | 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。 |
crbegin() | 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。 |
crend() | 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。 |
find(key) | 在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
lower_bound(key) | 返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
upper_bound(key) | 返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
equal_range(key) | 该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对(map 容器键值对唯一,因此该范围最多包含一个键值对)。 |
empty() | 若容器为空,则返回 true;否则 false。 |
size() | 返回当前 map 容器中存有键值对的个数。 |
max_size() | 返回 map 容器所能容纳键值对的最大个数,不同的操作系统,其返回值亦不相同。 |
operator[] | map容器重载了 [] 运算符,只要知道 map 容器中某个键值对的键的值,就可以向获取数组中元素那样,通过键直接获取对应的值。 |
at(key) | 找到 map 容器中 key 键对应的值,如果找不到,该函数会引发 out_of_range 异常。 |
insert() | 向 map 容器中插入键值对。 |
erase() | 删除 map 容器指定位置、指定键(key)值或者指定区域内的键值对。后续章节还会对该方法做重点讲解。 |
swap() | 交换 2 个 map 容器中存储的键值对,这意味着,操作的 2 个键值对的类型必须相同。 |
clear() | 清空 map 容器中所有的键值对,即使 map 容器的 size() 为 0。 |
emplace() | 在当前 map 容器中的指定位置处构造新键值对。其效果和插入键值对一样,但效率更高。 |
emplace_hint() | 在本质上和 emplace() 在 map 容器中构造新键值对的方式是一样的,不同之处在于,使用者必须为该方法提供一个指示键值对生成位置的迭代器,并作为该方法的第一个参数。 |
count(key) | 在当前 map 容器中,查找键为 key 的键值对的个数并返回。注意,由于 map 容器中各键值对的键的值是唯一的,因此该函数的返回值最大为 1。 |
2 map定义
map 容器定义在 <map> 头文件中,并位于 std 命名空间中。
#include <map>
using namespace std;
template < class Key, // 指定键(key)的类型
class T, // 指定值(value)的类型
class Compare = less<Key>, // 指定排序规则
class Alloc = allocator<pair<const Key,T> > // 指定分配器对象的类型
> class map;
3 创建map容器
map<std::string, int>myMap;
map<std::string, int>myMap1{ {"C++",10},{"MFC",20} };
//map 容器中存储的键值对,其本质都是 pair 类模板创建的 pair 对象。因此,下面程序也可以创建出一模一样的 myMap 容器:
map<std::string, int>myMap2{ std::make_pair("C++",10),std::make_pair("QT",20) };
4 赋值map容器
注意,无论是调用复制构造函数还是调用拷贝构造函数,都必须保证这 2 个容器的类型完全一致。
std::map<std::string, int> disMap() {
std::map<std::string, int>tempMap{ {"C语言教程",10},{"STL教程",20} };
return tempMap;
}
int main()
{
map<std::string, int>myMap1{ {"C++",10},{"MFC",20} };
map<std::string, int>newMap(myMap1);
//调用 map 类模板的移动构造函数创建 newMap 容器
std::map<std::string, int>newMap1(disMap());
//通过调用 map 容器的双向迭代器,实现了在创建 newMap 容器的同时,将其初始化为包含一个 {"STL教程",20} 键值对的容器。
//std::map<std::string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
//std::map<std::string, int>newMap(++myMap.begin(), myMap.end());
}
5 map升序降序规则
我们可以手动修改 map 容器的排序规则。默认情况下,map 容器调用 std::less<T> 规则,根据容器内各键值对的键的大小,对所有键值对做升序排序。
map<string, int>myMap{ {"C++",10},{"STL教程",20} };
map<string, int, less<string> >myMap1{ {"C++",10},{"STL教程",20} };
map<string, int, greater<string> >myMap2{ {"C++",10},{"STL教程",20} };
在某些特定场景中,我们还需要为 map 容器自定义排序规则.后续讲解。
6 map容器迭代器
C++ STL 标准库为 map 容器配备的是双向迭代器(bidirectional iterator)。这意味着,map 容器迭代器只能进行 ++p、p++、--p、p--、*p 操作,并且迭代器之间只能使用 == 或者 != 运算符进行比较。
图中 Ei 表示的是 pair 类对象,即键值对。对于 map 容器来说,每个键值对的KEY的值都必须保证是唯一的。
6.1 map迭代器常用函数
成员方法 | 功能 |
---|---|
begin() | 返回指向容器中第一个(注意,是已排好序的第一个)键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
end() | 返回指向容器最后一个元素(注意,是已排好序的最后一个)所在位置后一个位置的双向迭代器,通常和 begin() 结合使用。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
rbegin() | 返回指向最后一个(注意,是已排好序的最后一个)元素的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。 |
rend() | 返回指向第一个(注意,是已排好序的第一个)元素所在位置前一个位置的反向双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的反向双向迭代器。 |
cbegin() | 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。 |
cend() | 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。 |
crbegin() | 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。 |
crend() | 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改容器内存储的键值对。 |
find(key) | 在 map 容器中查找键为 key 的键值对,如果成功找到,则返回指向该键值对的双向迭代器;反之,则返回和 end() 方法一样的迭代器。另外,如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
lower_bound(key) | 返回一个指向当前 map 容器中第一个大于或等于 key 的键值对的双向迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
upper_bound(key) | 返回一个指向当前 map 容器中第一个大于 key 的键值对的迭代器。如果 map 容器用 const 限定,则该方法返回的是 const 类型的双向迭代器。 |
equal_range(key) | 该方法返回一个 pair 对象(包含 2 个双向迭代器),其中 pair.first 和 lower_bound() 方法的返回值等价,pair.second 和 upper_bound() 方法的返回值等价。也就是说,该方法将返回一个范围,该范围中包含的键为 key 的键值对(map 容器键值对唯一,因此该范围最多包含一个键值对)。 |
6.2 迭代器遍历map 容器
6.2.1 begin()/end()遍历map 容器
//创建并初始化 map 容器
map<string, string>myMap{ {"csdn","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343"},{"QT","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343"} ,{"web","www.begins.vip"} };
//调用 begin()/end() 组合,遍历 map 容器
for (auto iter = myMap.begin(); iter != myMap.end(); ++iter) {
cout << iter->first << " " << iter->second << endl;
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
6.2.2 rbegin()/rend()遍历map 容器
//调用 rbegin()/rend() 组合,遍历 map 容器
for (auto iter = myMap.rbegin(); iter != myMap.rend(); ++iter) {
cout << iter->first << " " << iter->second << endl;
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
6.2.3 使用find查找Value
//查找键为 "web" 的键值对
auto iter = myMap.find("web");
//从 iter 开始,遍历 map 容器
for (; iter != myMap.end(); ++iter) {
cout << iter->first << " " << iter->second << endl;
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
6.2.4 lower_bound(key)
lower_bound(key) 返回的是指向第一个键不小于 key 的键值对的迭代器;
//找到第一个键的值不小于 "web" 的键值对
auto iter = myMap.lower_bound("web");
cout << "lower:" << iter->first << " " << iter->second << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
6.2.5 upper_bound(key)
upper_bound(key) 返回的是指向第一个键大于 key 的键值对的迭代器;
//找到第一个键的值大于 "web" 的键值对
iter = myMap.upper_bound("web");
cout << "upper:" << iter->first << " " << iter->second << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
lower_bound(key) 和 upper_bound(key) 更多用于 multimap 容器,在 map 容器中很少用到。
6.2.6 equal_range(key)
equal_range(key) 成员方法可以看做是 lower_bound(key) 和 upper_bound(key) 的结合体,该方法会返回一个 pair 对象,其中的 2 个元素都是迭代器类型,其中 pair.first 实际上就是 lower_bound(key) 的返回值,而 pair.second 则等同于 upper_bound(key) 的返回值。
//创建一个 pair 对象,来接收 equal_range() 的返回值
pair <std::map<string, string>::iterator, std::map<string, string>::iterator> myPair = myMap.equal_range("web");
//通过遍历,输出 myPair 指定范围内的键值对
for (auto iter = myPair.first; iter != myPair.second; ++iter) {
cout << iter->first << " " << iter->second << endl;
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
和 lower_bound(key)、upper_bound(key) 一样,该方法也更常用于 multimap 容器,因为 map 容器中各键值对的键的值都是唯一的,因此通过 map 容器调用此方法,其返回的范围内最多也只有 1 个键值对。
7 map容器获取Value
map 容器中存储的都是 pair 类型的键值对,但几乎在所有使用 map 容器的场景中,经常要做的不是找到指定的 pair 对象(键值对),而是从该容器中找到某个键对应的值。
注意,使用 map 容器存储的各个键值对,其键的值都是唯一的,因此指定键对应的值最多有 1 个。
7.1 使用下标 [ ]
//创建并初始化 map 容器
map<string, string>myMap{ {"csdn","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343"},{"QT","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343"} ,{"web","www.begins.vip"} };
string cValues = myMap["QT"];
cout << cValues << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
7.1.1 下标添加
当 map 容器中确实存有包含该指定键的键值对,借助重载的 [ ] 运算符才能成功获取该键对应的值;反之,若当前 map 容器中没有包含该指定键的键值对,则此时使用 [ ] 运算符将不再是访问容器中的元素,而变成了向该 map 容器中增添一个键值对。其中,该键值对的键用 [ ] 运算符中指定的键,其对应的值取决于 map 容器规定键值对中值的数据类型,如果是基本数据类型,则值为 0;如果是 string 类型,其值为 "",即空字符串(即使用该类型的默认值作为键值对的值)。
map<std::string, int>myMap2;
int cValue = myMap2["Python"];
for (auto i = myMap.begin(); i != myMap.end(); ++i) {
cout << i->first << " " << i->second << endl;
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
7.1.2 Key相同进行添加
myMap["database"] = "https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343";
myMap["web"] = "https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343";
for (auto i = myMap.begin(); i != myMap.end(); ++i) {
cout << i->first << " " << i->second << endl;
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
7.2 使用at()
除了借助 [ ] 运算符获取 map 容器中指定键对应的值,还可以使用 at() 成员方法。和前一种方法相比,at() 成员方法也需要根据指定的键,才能从容器中找到该键对应的值;不同之处在于,如果在当前容器中查找失败,该方法不会向容器中添加新的键值对,而是直接抛出 out_of_range 异常。
//创建并初始化 map 容器
map<string, string>myMap{ {"csdn","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343"},{"QT","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343"} ,{"web","www.begins.vip"} };
cout << myMap.at("QT") << endl; //未查找到会报错
//下面一行代码会引发 out_of_range 异常
//cout << myMap.at("Python") << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
7.3 find()查找
find() 成员方法间接实现此目的。和以上 2 种方式不同的是,该方法返回的是一个迭代器,即如果查找成功,该迭代器指向查找到的键值对;反之,则指向 map 容器最后一个键值对之后的位置(和 end() 成功方法返回的迭代器一样)。
map< std::string, std::string >::iterator myIter = myMap.find("QT");
cout << myIter->first << " " << myIter->second << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
注意,此程序中如果 find() 查找失败,会导致第 13 行代码运行出错。因为当 find() 方法查找失败时,其返回的迭代器指向的是容器中最后一个键值对之后的位置,即不指向任何有意义的键值对,也就没有所谓的 first 和 second 成员了。
7.4 遍历整个 map 容器
for (auto iter = myMap.begin(); iter != myMap.end(); ++iter) {
//调用 string 类的 compare() 方法,找到一个键和指定字符串相同的键值对
if (!iter->first.compare("QT")) {
cout << iter->first << " " << iter->second << endl;
}
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
在 map 容器存储的键值对中,获取指定键对应的值”的角度出发,更推荐使用 at() 成员方法,因为该方法既简单又安全。
8 map insert()插入数据
8.1 下标插入数据
map<string, string> mymap{ {"csdn","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343"} };
//向 map 容器添加新键值对
mymap["web"] = "www.begins.vip";
//修改 map 容器已存储键值对中,指定键对应的值
mymap["web"] = "https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343/";
for (auto i = mymap.begin(); i != mymap.end(); ++i) {
cout << i->first << " " << i->second << endl;
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
8.2 insert()插入
insert() 方法的语法格式有以下 2 种:
1. 传递键值对 对于插入成功的 insert() 方法,其返回的 pair 对象中包含一个指向新插入键值对的迭代器和值为 1 的 bool 变量
2.右值引用的方式传递键值对 对于插入失败的 insert() 方法,同样会返回一个 pair 对象,其中包含一个指向 map 容器中键为 "STL教程" 的键值对和值为 0 的 bool 变量。
//创建一个空 map 容器
map<string, string> mymap2;
//创建一个真实存在的键值对变量
pair<string, string> STL = { "csdn","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343" };
//创建一个接收 insert() 方法返回值的 pair 对象
pair<map<string, string>::iterator, bool> ret;
//插入 STL,由于 STL 并不是临时变量,因此会以第一种方式传参
ret = mymap2.insert(STL);
cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
//以右值引用的方式传递临时的键值对变量
ret = mymap2.insert({ "web","www.begins.vip" });
//ret = mymap.insert(make_pair("web","www.begins.vip")); //相同
cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
//插入失败 容器没有任何改变
ret = mymap2.insert({ "csdn","aaa" });
cout << "ret.iter = <{" << ret.first->first << ", " << ret.first->second << "}, " << ret.second << ">" << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
8.3 指定位置插入
//创建一个空 map 容器
map<string, string> mymap3;
//创建一个真实存在的键值对变量
pair<string, string> STL2 = { "csdn","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343" };
//指定要插入的位置
map<string, string>::iterator it = mymap3.begin();
//向 it 位置以普通引用的方式插入 STL2
auto iter1 = mymap3.insert(it, STL2);
cout << iter1->first << " " << iter1->second << endl;
//向 it 位置以右值引用的方式插入临时键值对
auto iter2 = mymap3.insert(it, pair<string, string>("web", "www.begins.vip"));
cout << iter2->first << " " << iter2->second << endl;
//插入失败样例
auto iter3 = mymap3.insert(it, pair<string, string>("csdn", "aaa"));
cout << iter3->first << " " << iter3->second << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
8.4 插入多个键值对
//创建空的 map 容器
map<string, string>mymap4;
//向 mymap4 容器中添加 3 个键值对
mymap4.insert({ {"c++", "https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343"},
{ "mfc","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343" },
{ "qt","https://blog.csdn.net/qq_37529913?spm=1001.2101.3001.5343" } });
for (auto iter = mymap4.begin(); iter != mymap4.end(); ++iter) {
cout << iter->first << " " << iter->second << endl;
}
cout << "-------------------------------------------------------------------" << endl;
cout << "-------------------------------------------------------------------" << endl;
9 删除
// 删除迭代器指向位置的键值对,并返回一个指向下一元素的迭代器
iterator erase( iterator pos )
// 删除一定范围内的元素,并返回一个指向下一元素的迭代器
iterator erase( const_iterator first, const_iterator last );
// 根据Key来进行删除, 返回删除的元素数量,在map里结果非0即1
size_t erase( const key_type& key );
// 清空map,清空后的size为0
void clear();
10 operator[]和insert() 如何选择与效率对比
C++里面的map和unordered_map提供的两个添加函数:
map::operator[] 设计目的:添加和更新,主要是为了 更新;
map::insert 设计目的:插入新的元素
10.1 operator
operator 首先检查 map中是否存在 键k了,如果没有存在,键k就会被加入到 map中,并且 v作为相应的值。如果 k已经存在于映射表中了,则与之关联的值将被更新为 v。
operator[]返回一个引用,它指向鱼 k相关联的值的对象。然后 v被赋值给该引用所指向的对象。如果键值 k已经有了相关联的值,则该值被更新。但是如果 k还没有在映射表中的话,那就没有 operator[]可以指向的值对象,在这种情况下,它使用 值类型的默认构造参数创建一个新的对象,然后 operator[]就能返回一个指向该新对象的引用了。
什么使用 operator[]去添加元素会降低性能?因为如果我们 map中没有这个键值的话,我们就会多消耗运行三个函数的时间:一个是用于创建默认构造函数的临时对象,一个是用于析构该临时对象,一个是调用 类的赋值操作符函数进行赋值操作。
10.2 insert
map中没有相应的键值的话,我们就要用 insert添加值更快,效率也会相应提高。
operator[]是 先默认构造一个函数,然后立即赋给它新的值;而 insert是直接使用我们所需要的值构造一个新的类对象,然后直接插入到 map中去。当需要更新 map中的值的时候,就需要使用 operator成员函数了。当然我们可以写一个函数用来自动处理这个逻辑,当然一般应用程序不需要这么做。
以下博客部分内容借鉴自:http://c.biancheng.net/stl/。
C++ STL 容器、迭代器、适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120052137 C++ STL deque容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118676574
C++ STL vector容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118676109
C++ STL list容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118676917
C++ STL forward_list容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118687348
C++ STL array 容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118688364
C++ STL pair 类模板(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118714852
C++ STL map容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118741670
C++ STL map emplace()和emplace_hint()(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118771777
C++ STL multimap容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118773021
C++ STL Set容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/118918940
C++ STL multiset容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119624779
C++ STL unordered_map容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119689199
C++ STL unordered_set容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119709019
C++ STL unordered_multiset容器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119709079
C++ STL stack容器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119723782
C++ STL queue容器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119746246
C++ STL priority_queue容器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119770527
C++ STL reverse_iterator反向迭代器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119814820
C++ STL insert_iterator插入迭代器适配器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119834378
C++ STL stream_iterator流迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119834429
C++ STL streambuf_iterator流缓冲区迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119850048
C++ STL move_iterator移动迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/119859888
C++ STL advance()函数(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008250
C++ STL distance()函数(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008300
C++ STL iterator迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008346
C++ STL const_iterator转换为iterator类型迭代器(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008324
C++ STL begin()和end()函数(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008459
C++ STL prev()和next()函数(深入了解,一文学会) https://blog.csdn.net/qq_37529913/article/details/120008481