在 C++ 中,unordered_map 的 at() 和 [] 都可以访问元素,但它们在行为上有重要区别:
[]运算符
cpp
unordered_map<string, int> m = {{"apple", 1}};
m["apple"] = 2; // 修改已存在的元素
m["banana"] = 3; // 如果"banana"不存在,会创建并插入,值被值初始化(int为0)
int val = m["orange"]; // 会创建"orange"键,值为0
特点:
• 如果键不存在,会自动插入该键(值被默认构造)
• 可用于插入新元素
• 返回值的引用
• 不是 const 成员函数,不能在 const unordered_map 上使用
at()方法
cpp
unordered_map<string, int> m = {{"apple", 1}};
int val1 = m.at("apple"); // 正常访问,返回1
int val2 = m.at("banana"); // 抛出 std::out_of_range 异常
特点:
• 如果键不存在,抛出 std::out_of_range 异常
• 不会插入新元素
• 有 const 版本,可以在 const unordered_map 上使用
• 更加安全,能避免意外插入
- 关键区别对比
| 特性 | operator [] |
at() |
|---|---|---|
| 键不存在时 | 插入新键值对 | 抛出异常 |
| 可否用于插入 | ✓ | ✗ |
| 异常安全性 | 不抛异常 | 抛 std::out_of_range |
const 版本 |
✗ | ✓ |
| 返回类型 | 引用 | 引用(const 或非 const) |
- 使用建议
cpp
// 推荐做法:
unordered_map<string, int> m;
// 检查键是否存在再访问
if (m.find("key") != m.end()) {
int val = m["key"]; // 或 m.at("key")
}
// 使用 at() 进行安全访问
try {
int val = m.at("key");
} catch (const std::out_of_range& e) {
// 处理键不存在的情况
}
// 使用 [] 进行插入或修改
m["new_key"] = 10; // 直接插入
// 遍历访问(安全)
for (const auto& [key, value] : m) {
// 安全访问,不会插入新元素
}
- 总结
• 想检查键是否存在时:用 find() 或 contains() (C++20)
• 确保键存在时:用 at() 更安全
• 想插入或修改时:用 []
• 访问 const map 时:只能用 at() 或迭代器