C++ STL map获取键对应值的几种方法(超详细)
我们知道,map 容器中存储的都是 pair 类型的键值对,但几乎在所有使用 map 容器的场景中,经常要做的不是找到指定的 pair 对象(键值对),而是从该容器中找到某个键对应的值。
1) map 类模板中对
举个例子:
注意,只有当 map 容器中确实存有包含该指定键的键值对,借助重载的 [ ] 运算符才能成功获取该键对应的值;反之,若当前 map 容器中没有包含该指定键的键值对,则此时使用 [ ] 运算符将不再是访问容器中的元素,而变成了向该 map 容器中增添一个键值对。其中,该键值对的键用 [ ] 运算符中指定的键,其对应的值取决于 map 容器规定键值对中值的数据类型,如果是基本数据类型,则值为 0;如果是 string 类型,其值为 "",即空字符串(即使用该类型的默认值作为键值对的值)。
举个例子:
实际上,[ ] 运算符确实有“为 map 容器添加新键值对”的功能,但前提是要保证新添加键值对的键和当前 map 容器中已存储的键值对的键都不一样。例如:
2) 除了借助 [ ] 运算符获取 map 容器中指定键对应的值,还可以使用 at() 成员方法。和前一种方法相比,at() 成员方法也需要根据指定的键,才能从容器中找到该键对应的值;不同之处在于,如果在当前容器中查找失败,该方法不会向容器中添加新的键值对,而是直接抛出 out_of_range 异常。
举个例子:
除了可以直接获取指定键对应的值之外,还可以借助 find() 成员方法间接实现此目的。和以上 2 种方式不同的是,该方法返回的是一个迭代器,即如果查找成功,该迭代器指向查找到的键值对;反之,则指向 map 容器最后一个键值对之后的位置(和 end() 成功方法返回的迭代器一样)。
举个例子:
如果以上方法都不适用,我们还可以遍历整个 map 容器,找到包含指定键的键值对,进而获取该键对应的值。比如:
庆幸的是,map 容器的类模板中提供了以下 2 种方法,可直接获取 map 容器指定键对应的值。注意,使用 map 容器存储的各个键值对,其键的值都是唯一的,因此指定键对应的值最多有 1 个。
1) map 类模板中对
[ ]
运算符进行了重载,这意味着,类似于借助数组下标可以直接访问数组中元素,通过指定的键,我们可以轻松获取 map 容器中该键对应的值。举个例子:
#include <iostream> #include <map> // map #include <string> // string using namespace std; int main() { //创建并初始化 map 容器 std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"}, {"C语言教程","http://c.biancheng.net/c/"}, {"Java教程","http://c.biancheng.net/java/"} }; string cValue = myMap["C语言教程"]; cout << cValue << endl; return 0; }程序执行结果为:
http://c.biancheng.net/c/
可以看到,在第 11 行代码中,通过指定键的值为 "C语言教程",借助重载的 [ ] 运算符,就可以在 myMap 容器中直接找到该键对应的值。注意,只有当 map 容器中确实存有包含该指定键的键值对,借助重载的 [ ] 运算符才能成功获取该键对应的值;反之,若当前 map 容器中没有包含该指定键的键值对,则此时使用 [ ] 运算符将不再是访问容器中的元素,而变成了向该 map 容器中增添一个键值对。其中,该键值对的键用 [ ] 运算符中指定的键,其对应的值取决于 map 容器规定键值对中值的数据类型,如果是基本数据类型,则值为 0;如果是 string 类型,其值为 "",即空字符串(即使用该类型的默认值作为键值对的值)。
举个例子:
#include <iostream> #include <map> // map #include <string> // string using namespace std; int main() { //创建空 map 容器 std::map<std::string, int>myMap; int cValue = myMap["C语言教程"]; for (auto i = myMap.begin(); i != myMap.end(); ++i) { cout << i->first << " "<< i->second << endl; } return 0; }程序执行结果为:
C语言教程 0
显然,对于空的 myMap 容器来说,其内部没有以 "C语言教程" 为键的键值对,这种情况下如果使用 [ ] 运算符获取该键对应的值,其功能就转变成了向该 myMap 容器中添加一个<"C语言教程",0>
键值对(由于 myMap 容器规定各个键值对的值的类型为 int,该类型的默认值为 0)。实际上,[ ] 运算符确实有“为 map 容器添加新键值对”的功能,但前提是要保证新添加键值对的键和当前 map 容器中已存储的键值对的键都不一样。例如:
#include <iostream> #include <map> // map #include <string> // string using namespace std; int main() { //创建空 map 容器 std::map<string, string>myMap; myMap["STL教程"]="http://c.biancheng.net/java/"; myMap["Python教程"] = "http://c.biancheng.net/python/"; myMap["STL教程"] = "http://c.biancheng.net/stl/"; for (auto i = myMap.begin(); i != myMap.end(); ++i) { cout << i->first << " " << i->second << endl; } return 0; }程序执行结果为:
Python教程 http://c.biancheng.net/python/
STL教程 http://c.biancheng.net/stl/
2) 除了借助 [ ] 运算符获取 map 容器中指定键对应的值,还可以使用 at() 成员方法。和前一种方法相比,at() 成员方法也需要根据指定的键,才能从容器中找到该键对应的值;不同之处在于,如果在当前容器中查找失败,该方法不会向容器中添加新的键值对,而是直接抛出 out_of_range 异常。
举个例子:
#include <iostream> #include <map> // map #include <string> // string using namespace std; int main() { //创建并初始化 map 容器 std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"}, {"C语言教程","http://c.biancheng.net/c/"}, {"Java教程","http://c.biancheng.net/java/"} }; cout << myMap.at("C语言教程") << endl; //下面一行代码会引发 out_of_range 异常 //cout << myMap.at("Python教程") << endl; return 0; }程序执行结果为:
http://c.biancheng.net/c/
程序第 12 行代码处,通过 myMap 容器调用 at() 成员方法,可以成功找到键为 "C语言教程" 的键值对,并返回该键对应的值;而第 14 行代码,由于当前 myMap 容器中没有以 "Python教程" 为键的键值对,会导致 at() 成员方法查找失败,并抛出 out_of_range 异常。除了可以直接获取指定键对应的值之外,还可以借助 find() 成员方法间接实现此目的。和以上 2 种方式不同的是,该方法返回的是一个迭代器,即如果查找成功,该迭代器指向查找到的键值对;反之,则指向 map 容器最后一个键值对之后的位置(和 end() 成功方法返回的迭代器一样)。
举个例子:
#include <iostream> #include <map> // map #include <string> // string using namespace std; int main() { //创建并初始化 map 容器 std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"}, {"C语言教程","http://c.biancheng.net/c/"}, {"Java教程","http://c.biancheng.net/java/"} }; map< std::string, std::string >::iterator myIter = myMap.find("C语言教程"); cout << myIter->first << " " << myIter->second << endl; return 0; }程序执行结果为:
C语言教程 http://c.biancheng.net/c/
注意,此程序中如果 find() 查找失败,会导致第 13 行代码运行出错。因为当 find() 方法查找失败时,其返回的迭代器指向的是容器中最后一个键值对之后的位置,即不指向任何有意义的键值对,也就没有所谓的 first 和 second 成员了。
如果以上方法都不适用,我们还可以遍历整个 map 容器,找到包含指定键的键值对,进而获取该键对应的值。比如:
#include <iostream> #include <map> // map #include <string> // string using namespace std; int main() { //创建并初始化 map 容器 std::map<std::string, std::string>myMap{ {"STL教程","http://c.biancheng.net/stl/"}, {"C语言教程","http://c.biancheng.net/c/"}, {"Java教程","http://c.biancheng.net/java/"} }; for (auto iter = myMap.begin(); iter != myMap.end(); ++iter) { //调用 string 类的 compare() 方法,找到一个键和指定字符串相同的键值对 if (!iter->first.compare("C语言教程")) { cout << iter->first << " " << iter->second << endl; } } return 0; }程序执行结果为:
C语言教程 http://c.biancheng.net/c/
本节所介绍的几种方法中,仅从“在 map 容器存储的键值对中,获取指定键对应的值”的角度出发,更推荐使用 at() 成员方法,因为该方法既简单又安全。
相关文章
- C++ STL unordered_map获取元素的4种方法(超级详细)
- C++ STL map容器详解
- C++ STL map容器迭代器用法详解
- C++ STL map insert()插入数据的4种方式
- C++ STL map emplace()和emplace_hint()方法详解
- C++ STL map删除键值对:erase()和clear()方法
- C++ STL unordered_map容器用法详解
- C++ STL unordered_map删除元素:erase()和clear()
- C++ map,STL map详解
- C++ map(STL map)构造元素(emplace和emplace_hint函数)详解