文章目录
- 【 1. 基本原理 】
- 【 2. map 的创建 】
- 2.1 调用默认构造函数,创建一个空的 map
- 2.2 map 被构造的同时初始化
- 2.3 通过一个 map 初始化另一个 map
- 2.4 取已建 map 中指定区域内的键值对,初始化新的 map
- 2.5 指定排序规则
- 【 2. map 元素的操作 】
- 实例 - 查找键
- 实例 - map 某个键对应的值自加1
- 【 3 map 支持的成员方法 】
- 实例 - 输出map元素数量以及各个键值对
【 1. 基本原理 】
- map 容器存储的都是 pair 对象,用 pair 类模板创建的键值对,即
pair<const K, T>
类型(其中 K 和 T 分别表示键和值的数据类型)的键值对元素。其中,各个键值对的键和值可以是任意数据类型,包括 C++ 基本数据类型(int、char、double 等)、使用结构体或类自定义的类型。通常情况下,map 容器中存储的各个键值对都选用 string 字符串作为键的类型。 - 与此同时,在使用 map 容器存储多个键值对时, map容器会自动根据各键值对中键的大小,按照既定的规则进行 自动排序。默认情况下,map 容器选用 std::less<T>排序规则(其中 T 表示键的数据类型),其会根据键的大小对所有键值 默认做升序排序。当然,根据实际情况的需要,我们可以手动指定 map 容器的排序规则,既可以选用 STL 标准库中提供的其它排序规则(比如std::greater<T>),也可以自定义排序规则。
- map 容器中存储的各个键值对 不仅键独一无二,键的类型也会用 const 修饰,这意味着使用 map 容器存储的各个键值对, 键 既不能重复也不能被修改。
【 2. map 的创建 】
- map 容器定义在 <map> 头文件 中,并位于 std 命名空间 中。
- map 容器的模板定义如下:
- map 容器模板有 4 个参数,其中后 2 个参数都设有默认值。大多数场景中,我们只需要设定前 2 个参数的值,有些场景可能会用到第 3 个参数,但最后一个参数几乎不会用到。
template < class Key, // 指定键(key)的类型class T, // 指定值(value)的类型class Compare = less<Key>, // 指定排序规则class Alloc = allocator<pair<const Key,T> > // 指定分配器对象的类型> class map;
2.1 调用默认构造函数,创建一个空的 map
- 通过此方式创建出的 myMap 容器,初始状态下是空的,即没有存储任何键值对。鉴于空 map 容器可以根据需要随时添加新的键值对,因此创建空 map 容器是比较常用的。
map<string, int>myMap;
2.2 map 被构造的同时初始化
- 在创建 map 容器的同时,也可以进行初始化,比如:
由此,myMap 容器在初始状态下,就包含有 2 个键值对。
map<string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
- 再次强调,map 容器中存储的键值对,其本质都是 pair 类模板创建的 pair 对象。因此,下面程序也可以创建出一模一样的 myMap 容器:
map<string, int>myMap{make_pair("C语言程",10),make_pair("STL教程",20)};
2.3 通过一个 map 初始化另一个 map
- 在某些场景中,可以利用先前已创建好的 map 容器,再创建一个新的 map 容器。 无论是调用复制构造函数还是调用拷贝构造函数,前提是需要保证两个容器的类型一致。
- 通过调用 map 容器的 拷贝构造函数,即可成功创建一个和 myMap 完全一样的 newMap 容器。
map<string, int>newMap(myMap);
- C++ 11 标准中,还为 map 容器增添了 移动构造函数。当有临时的 map 对象作为参数,传递给要初始化的 map 容器时,此时就会调用移动构造函数。举个例子:
#创建一个会返回临时 map 对象的函数
map<string,int> disMap()
{map<string, int>tempMap{ {"C语言教程",10},{"STL教程",20} };return tempMap;
}
//调用 map 类模板的移动构造函数创建 newMap 容器
map<string, int>newMap(disMap());
2.4 取已建 map 中指定区域内的键值对,初始化新的 map
- map 类模板还支持取已建 map 容器中指定区域内的键值对,创建并初始化新的 map 容器。例如:
这里,通过调用 map 容器的双向迭代器,实现了在创建 newMap 容器的同时,将其初始化为包含一个 {“STL教程”,20} 键值对的容器。
map<string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
map<string, int>newMap(++myMap.begin(), myMap.end());
2.5 指定排序规则
- 在以上几种创建 map 容器的基础上,我们都可以手动修改 map 容器的排序规则。
- 默认情况下,map 容器调用 std::less<T> 规则,根据容器内各键值对的键的大小,对所有键值对 默认做升序排序。
因此,如下 2 行创建 map 容器的方式,其实是等价的:
map<string, int>myMap{ {"C语言教程",10},{"STL教程",20} };
map<string, int, less<string> >myMap{ {"C语言教程",10},{"STL教程",20} };
以上 2 种创建方式生成的 myMap 容器,其内部键值对排列的顺序为:
<“C语言教程”, 10>
<“STL教程”, 20>
- 下面程序手动修改了 myMap 容器的排序规则,令其 指定做降序排序:
map<string, int, greater<string> >myMap{ {"C语言教程",10},{"STL教程",20} };
此时,myMap 容器内部键值对排列的顺序为:
<“STL教程”, 20>
<“C语言教程”, 10>
【 2. map 元素的操作 】
- 通过指定 键 的方式 访问键值对
如果 该键存在,则返回该键对应的值;否则返回0。
myMap[ 要查找的键 ]
- 通过迭代器的方式访问键值对
t->first为该迭代器对应的键,t->second为该迭代器对应的值。
auto t = myMap.begin();
cout << t->first << t->second << endl;//t->first为键,t->second为值
实例 - 查找键
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {map<string,int>myMap;myMap.emplace("Nami", 98);myMap.emplace("Luffy", 99);myMap.emplace("Soro", 97);cout << myMap["Nami"] << endl;//存在键相应的键值对,返回对应的值cout << myMap["Sanj"] << endl; //没有键对应的键值对,返回0auto t = myMap.begin();cout << t->first << t->second << endl;//t->first为键,t->second为值return 0;
}
实例 - map 某个键对应的值自加1
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {map<string,int>myMap;myMap.emplace("Nami", 1);myMap["Nami"]++;cout << myMap["Nami"] << endl;auto t = myMap.begin();t->second = t->second + 1;cout << t->second << endl;return 0;
}
【 3 map 支持的成员方法 】
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。 |
实例 - 输出map元素数量以及各个键值对
- 创建 1个 map,输出map元素数量,最后输出各个键值对。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {//创建空 map 容器,默认根据个键值对中键的值,对键值对做降序排序map<string, string,greater<string>>myMap;//调用 emplace() 方法,直接向 myMap 容器中指定位置构造新键值对myMap.emplace("C语言教程", "http://c.biancheng.net/c/");myMap.emplace("Python教程", "http://c.biancheng.net/python/");myMap.emplace("STL教程", "http://c.biancheng.net/stl/");//输出当前 myMap 容器存储键值对的个数cout << "myMap size==" << myMap.size() << endl;//输出键值对if (!myMap.empty()) //判断当前 myMap 容器是否为空{//借助 myMap 容器迭代器,将该容器的键值对逐个输出for (auto i = myMap.begin(); i != myMap.end(); ++i)cout << i->first << " " << i->second << endl;}return 0;
}
- 统计字符串中各字母字符对应的个数
#include <iostream>
#include<map>
using namespace std;
int main() {char str[100] = { 0 };cin.getline(str, sizeof(str));map<char, int>maps;for (int i = 0; str[i] != '\0'; i++) {if (isalpha(str[i]))//判断是否是字符maps[str[i]]++;//maps[str[i]]++指的是取出map对应key的value值再累加,如果没有对应的键则会自动加入map中 }for (auto it = maps.begin(); it != maps.end(); it++){cout << it->first << ":" << it->second << endl;}return 0;
}