C++11起推荐用范围for遍历map,直接获取const key和可变value的pair;边遍历边删除须用显式迭代器配合erase返回值;查找应优先用find()避免operator[]的插入副作用。

用 for-range 遍历 map 最简洁安全
现代 C++(C++11 起)推荐用范围 for 循环,避免迭代器失效和手动管理。直接拿到 std::pair,注意 key 是 const —— 这是 map 的设计约束,不能通过遍历变量修改 key。
常见错误:写成 for (auto& p : my_map) { p.first = 123; } → 编译失败,因为 p.first 是 const 引用;想改值只能操作 p.second。
实操建议:
- 读取键值对:用
for (const auto& p : my_map),最省资源 - 需要修改 value:用
for (auto& p : my_map),此时p.second可写 - 只遍历 key:用
for (const auto& kv : my_map) { kv.first; } - 只遍历 value:同理用
kv.second,别试图用my_map.values()(C++ 没这方法)
用迭代器遍历时注意 erase 的写法
如果边遍历边删除元素,不能用 for-range —— 它的底层迭代器在 erase 后会失效。必须用显式迭代器,并且 erase() 返回下一个有效迭代器(C++11 起),否则容易崩溃或跳过元素。
立即学习“C++免费学习笔记(深入)”;
典型错误写法:for (auto it = m.begin(); it != m.end(); ++it) { if (bad(it)) m.erase(it); } → it 在 erase 后已无效,++it 行为未定义。
正确写法:
for (auto it = m.begin(); it != m.end(); ) { if (bad(it)) it = m.erase(it); else ++it; }- 或者用 while:
auto it = m.begin(); while (it != m.end()) { if (bad(it)) it = m.erase(it); else ++it; } - 注意:
m.erase(it)返回的是下一个迭代器,不是 void(C++11 前是 void,那会儿得写it = m.erase(it++))
find() 和 [] 查找的区别很关键
operator[] 看似方便,但有副作用:查不到时会默认构造一个新元素插入 map,改变容器大小。而 find() 纯查询,不改动容器,返回 end() 表示未找到。
常见误用场景:循环里反复写 if (m[key] > 0) { ... } → 每次 key 不存在就插入一个零值,map 越来越大。
实操建议:
- 只读查找、避免副作用:一律用
if (auto it = m.find(key); it != m.end()) { ... it->second ... } - 需要“有则取,无则设默认值”:用
m.try_emplace(key, default_val)(C++17)或m.emplace(key, default_val).first->second -
[]仅用于明确要插入/更新的场景,比如计数:count[key]++
按 key 排序是 map 的默认行为,别手动 sort
std::map 底层是红黑树,key 自动升序排列(基于 std::less)。不需要、也不能对 map 调用 std::sort —— 它没有随机访问迭代器,sort 不接受它的迭代器类型。
容易踩的坑:
- 想按 value 排序?必须复制到 vector:
vector> v(m.begin(), m.end()); sort(v.begin(), v.end(), [](auto& a, auto& b) { return a.second - 想降序遍历 key?用
for (auto it = m.rbegin(); it != m.rend(); ++it),别 reverse map - 自定义比较函数:声明时传入,如
map,影响所有操作(包括 find、insert)> m;
性能提示:频繁按 value 查找或排序,说明 map 可能不是最优容器,考虑用 unordered_map + 备份 vector 或用 Boost.Bimap。










