unordered_map是C++11哈希表,平均O(1)操作但无序;需头文件;operator[]会默认构造插入,find()更安全;自定义key需提供哈希和==;rehash使所有迭代器失效。

unordered_map 是 C++11 引入的哈希表实现,查找、插入、删除平均时间复杂度为 O(1),但不保证元素顺序。它适合需要快速随机访问、且不需要排序的场景;如果需要有序遍历或范围查询,该用 map。
怎么声明和初始化 unordered_map
头文件是 <unordered_map></unordered_map>,模板参数依次是键类型、值类型、哈希函数、相等比较函数(后两者通常用默认):
std::unordered_map<std::string, int> m; m["apple"] = 5; m["banana"] = 3;
支持多种初始化方式:
- 空构造:
std::unordered_map<int std::string> m;</int> - 列表初始化:
std::unordered_map<int char> m = {{1,'a'}, {2,'b'}};</int> - 从另一个
unordered_map构造:std::unordered_map<int int> m2(m1);</int> - 指定桶数量(影响初始哈希表大小):
std::unordered_map<int int> m(1024);</int>—— 这能减少后续 rehash 次数,但不能省略类型参数
find() 和 operator[] 的关键区别
operator[] 在键不存在时会**默认构造一个值并插入**,这可能触发意外副作用(比如对自定义类调用无参构造函数),且无法区分“查到空值”和“键不存在”:
立即学习“C++免费学习笔记(深入)”;
std::unordered_map<std::string, std::vector<int>> m; auto& v = m["missing"]; // v 被默认构造为空 vector,m 中多了一项!
而 find() 安全、明确,返回 iterator,查不到则等于 end():
- 查存在性:
if (m.find("key") != m.end()) { ... } - 取值(需解引用):
int val = m.find("key")->second;(务必先检查是否有效) - 想安全取值又不想插入?用
at()—— 键不存在时抛std::out_of_range
自定义类型作 key 怎么办
必须提供哈希函数和相等比较函数。例如用 struct Point { int x, y; }; 作 key:
struct Point {
int x, y;
bool operator==(const Point& p) const { return x == p.x && y == p.y; }
};
struct PointHash {
size_t operator()(const Point& p) const {
return std::hash<int>{}(p.x) ^ (std::hash<int>{}(p.y) << 1);
}
};
std::unordered_map<Point, std::string, PointHash, std::equal_to<Point>> m;注意点:
- 哈希函数不能只返回
x + y或x * y,容易冲突;推荐用标准库std::hash组合 -
operator==必须定义,且语义要和哈希一致:若a == b,则hash(a) == hash(b) - C++20 起可对结构加
[[maybe_unused]]等简化,但核心逻辑不变
最常被忽略的是:unordered_map 的迭代器失效规则比 vector 更复杂——单次插入/删除只让指向被操作元素的迭代器失效,但 rehash(扩容)会让**所有迭代器失效**。如果在循环中边遍历边修改,务必小心。


















