C++ map怎么遍历 C++键值对容器常用操作速查【笔记】

9次阅读

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

C++ map怎么遍历 C++键值对容器常用操作速查【笔记】

用 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; }
  • 或者用 whileauto 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> m;,影响所有操作(包括 find、insert)

性能提示:频繁按 value 查找或排序,说明 map 可能不是最优容器,考虑用 unordered_map + 备份 vector 或用 Boost.Bimap。

text=ZqhQzanResources