Map类型

176 阅读4分钟

1 . Map的定义

map 是键-值对的集合。map 类型通常可理解为关联数组(associative array) :可使用键作为下标来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联, 而并非通过元素在数组中的位置来获取。

2 . Map对象的定义

要使用 map 对象,则必须包含 map 头文件。在定义 map 对象时,必须分别指明键和值的类型(value type).

// count number of times each word occurs in the input
map<string, int> word_count; // empty map from string to int

3 . Map的构造函数

map<k, v> m;创建一个名为 m 的空 map 对象, 其键和值的类型分别为 k 和 v
map<k, v>m(m2);创建 m2 的副本 m,m 与 m2 必须有相同的键类型和值类型
map<k, v>m(b, e);创建 map 类型的对象 m, 存储迭代器 b 和 e 标记的范围内所有元素的副本。元素的类型必须能转换为 pair<const k, v>

4 . map 定义的类型

map<K,V>::key_type在 map 容器中,用做索引的键的类型
map<K,V>::mapped_type在 map 容器中,键所关联的值的类型
map<K,V>::value_type一个 pair 类型,它的 first 元素具有 const map<K,V>::key_type 类型,而 second 元素则为 map<K,V>::mapped_type 类型
  • map 对象的元素是键-值对,也即每个元素包含两个部分:键以及由键关联的值。

value_type 是存储元素的键以及值的 pair 类型,而且键为 const。例如,word_count 数组的 value_type 为 pair<const string,int> 类型。

5 . 给Map添加元素

  • 该项工作可使用 insert 成员实现;
m.insert(e)e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则插入一个值为 e.second 的新元素;如果该键在 m 中已存在,则保持 m 不变。该函数返回一个pair 类型对象,包含指向键为 e.first 的元素的 map 迭代器,以及一个 bool 类型的对象,表示是否插入了该元素
m.insert(beg,end)beg 和 end 是标记元素范围的迭代器,其中的元素必须为m.value_type 类型的键-值对。对于该范围内的所有元素,如果它的键在 m 中不存在, 则将该键及其关联的值插入到 m。返回 void 类型
m.insert(iter,e)e 是一个用在 m 上的 value_type 类型的值。如果键(e.first)不在 m 中,则创建新元素,并以迭代器 iter 为起点搜索新元素存储的位置。返回一个迭代器,指向 m 中具有给定键的元素

传递给 insert 的实参相当笨拙。可用两种方法简化:使用 make_pair:

word_count.insert(make_pair("Anna", 1));
  • 先用下标操作符获取元素,然后给获取的元素赋值。

6 . 查找并读取 Map 中的元素

6 . 1 下标操作符给出了读取一个值的最简单方法:

but:

使用下标存在一个很危险的副作用:如果该键不在 map 容器中,那么下标操作会插入一个具有该键的新元素。但若是我们只想知道某元素是否存在,而当该元素不存在时,并不想做做插入运算。对于这种应用,则不能使用下标操作符来判断元素是否存在。

so: count 和 find,用于检查某个键是否存在而不会插入该键。

m.count(k)返回 m 中 k 的出现次数
m.find(k)如果 m 容器中存在按 k 索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器

注意:

  • count 成员的返回值只能是 0 或 1。map 容器只允许一个键对应一个实例, 所以 count 可有效地表明一个键是否存在。如果返回值非 0,则可以使用下标操作符来获取该键所关联的值,而不必担心这样做会在 map 中插入新元素:

7 . 从 Map 中删除元素

m.erase(k)删除 m 中键为 k 的元素。返回 size_type 类型的值,表示删除的元素个数
m.erase(p)从 m 中删除迭代器 p 所指向的元素。p 必须指向 m 中确实存在的元素,而且不能等于 m.end()。返回 void
m.erase(b,e)从 m 中删除一段范围内的元素, 该范围由迭代器对 b 和 e 标记。b 和 e 必须标记 m 中的一段有效范围: 即 b 和 e 都必须指向 m中的元素或最后一个元素的下一个位置。而且,b 和 e 要么相等(此时删除的范围为空),要么 b 所指向的元素必须出现在 e 所指向的元素之前。返回 void 类型

8 . Map 对象的遍历

与其他容器一样,map 同样提供 begin 和 end 运算,以生成用于遍历整个容器的迭代器。

// get iterator positioned on the first element 
map<string, int>::const_iterator 
map_it = word_count.begin(); 
// for each element in the map
while (map_it != word_count.end()) {
// print the element key, value pairs 
cout << map_it->first << " occurs " 
<< map_it->second << " times" << endl;
++map_it; // increment iterator to denote the next element }