C++11 std::map访问的使用小结
在C++中,std::map(有序关联容器,基于红黑树实现)通过key访问value主要有3种常用方式,各有适用场景和注意事项。
以下是详细说明和示例:
1. 使用operator[](最简洁,但有副作用)
std::map重载了[]运算符,直接通过key索引value。
- 行为:若key存在,返回对应value的引用;若key不存在,则自动插入一个新元素(key为给定值,value为默认构造的空值,如
int默认0、std::string默认空串)。 - 适用场景:确定key存在,或需要修改/新增value时使用。
- 缺点:意外插入新元素(可能导致逻辑错误);无法区分“访问不存在的key”和“访问存在的空值”。
示例代码:
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<int, std::string> fruitMap;
// 插入初始元素
fruitMap[1] = "Apple";
fruitMap[2] = "Banana";
// 访问存在的key
std::cout << "Key 1: " << fruitMap[1] << std::endl; // 输出 "Apple"
// 访问不存在的key(会自动插入新元素!)
std::cout << "Key 3 (new): " << fruitMap[3] << std::endl; // 输出空串,此时fruitMap多了{3, ""}
std::cout << "Now size: " << fruitMap.size() << std::endl; // 输出3(原2个+新增1个)
return 0;
}2. 使用at()(安全访问,C++11及以上)
std::map::at(key)返回key对应的value引用,若key不存在则抛出std::out_of_range异常。
- 行为:仅访问已存在的key,不修改容器;异常需手动捕获。
- 适用场景:确定key存在,或需要显式处理“key不存在”的错误(用异常处理)。
- 优点:无副作用(不会插入新元素);语义明确(“访问已存在的元素”)。
示例代码:
#include <iostream>
#include <map>
#include <string>
#include <stdexcept> // for std::out_of_range
int main() {
std::map<int, std::string> fruitMap = {{1, "Apple"}, {2, "Banana"}};
try {
// 访问存在的key
std::cout << "Key 2: " << fruitMap.at(2) << std::endl; // 输出 "Banana"
// 访问不存在的key(抛异常)
std::cout << "Key 3: " << fruitMap.at(3) << std::endl;
} catch (const std::out_of_range& e) {
std::cerr << "Error: " << e.what() << std::endl; // 输出 "map::at"
}
return 0;
}3. 使用find()(最安全,推荐用于不确定key是否存在的场景)
std::map::find(key)返回一个迭代器:
- 若key存在,迭代器指向该元素(
it->first是key,it->second是value); - 若key不存在,迭代器等于
map.end()(尾后迭代器)。 - 行为:无副作用(不插入新元素);需手动判断迭代器有效性。
- 适用场景:不确定key是否存在,需要安全访问(避免插入或异常)。
- 优点:完全可控;时间复杂度与
operator[]/at()相同(均为O(log n),红黑树查找)。
示例代码:
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<int, std::string> fruitMap = {{1, "Apple"}, {2, "Banana"}};
// 查找存在的key
auto it = fruitMap.find(1);
if (it != fruitMap.end()) {
std::cout << "Key 1: " << it->second << std::endl; // 输出 "Apple"
}
// 查找不存在的key
it = fruitMap.find(3);
if (it == fruitMap.end()) {
std::cout << "Key 3 not found." << std::endl; // 输出提示
}
return 0;
}总结:如何选择?
方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
operator[] | 确定key存在,或需要新增/修改value | 语法简洁 | 意外插入新元素 |
at() | 确定key存在,或用异常处理错误 | 无副作用,语义明确 | 依赖异常机制(开销) |
find() | 不确定key是否存在,需要安全访问 | 完全可控,无副作用 | 需手动判断迭代器 |
嵌入式开发中的注意事项
在资源受限的嵌入式环境中:
- 优先用
find():避免operator[]的意外插入(可能导致内存膨胀),也避免at()的异常开销(异常处理在嵌入式中有时禁用)。 - 若需频繁访问,可将
find()的结果缓存(如保存迭代器),减少重复查找。
扩展:Qt中的类似容器
如果你用Qt开发(如界面部分),Qt提供了QMap(类似std::map)和QHash(类似std::unordered_map),访问方式类似:
QMap::value(key):等价于std::map::at()(不插入新元素,不存在时返回默认值);QMap::operator[]:等价于std::map::operator[](不存在时插入);QMap::find(key):同std::map::find()。
到此这篇关于C++11 std::map访问的使用小结的文章就介绍到这了,更多相关C++11 std::map访问内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
C++实现分水岭算法(Watershed Algorithm)
这篇文章主要为大家详细介绍了C++实现分水岭算法Watershed Algorithm,具有一定的参考价值,感兴趣的小伙伴们可以参考一 下2018-01-01


最新评论