C++中std::multimap如何获取所有具有相同键的元素范围? (equal_range用法)

11次阅读

std::multimap::equal_range 返回一对迭代器,first 指向首个键匹配元素,second 指向匹配区间末尾后一位置(左闭右开);需用 for(it=first; it!=second; ++it) 安全遍历,不可解引用 second 或用

C++ 中 std::multimap 如何获取所有具有相同键的元素范围?(equal_range 用法)

std::multimap::equal_range 返回的是什么

它返回一个 std::pair,其中 first 指向第一个键等于给定值的元素,second 指向最后一个键等于该值的 ** 后一个位置 **(即左闭右开区间)。这不是“所有匹配元素的容器”,而是一对迭代器——你得自己遍历。

怎么用 equal_range 遍历所有相同键的元素

别直接解引用 second 迭代器;它可能等于 end(),解引用会崩溃。正确做法是用循环从 range.first 走到 range.second

auto range = mm.equal_range(key); for (auto it = range.first; it != range.second; ++it) {std::cout << it->second << "n"; // 注意:it->first 是 key,it->second 是值}
  • mmstd::multimap<k v></k> 实例
  • 如果 key 不存在,range.first == range.second,循环不执行,安全
  • 不要写 it —— multimap 迭代器只支持 <code>!=,不支持

为什么不用 find + while 循环找下一个相同键

因为 find 只返回第一个匹配项,后续必须手动调用 upper_bound 或反复 ++it 并检查 it->first == key,容易漏掉边界或越界。而 equal_range 是 O(log n) 一次定位,内部已优化,且语义清晰。

  • equal_range 在底层通常复用红黑树的查找逻辑,比多次 find 或手动推进更高效
  • 在并发读场景下,equal_range 返回的两个迭代器保证指向同一段连续逻辑区间,手动推进可能因中间插入导致迭代器失效或跳过元素
  • 注意:C++20 起 std::multimap 仍不支持 contains,所以 equal_range 仍是查“是否存在 + 取全部”的最小原子操作

常见错误:把 equal_range 当成 vector 或范围 for 直接用

以下写法是错的:

立即学习 C++ 免费学习笔记(深入)”;

for (auto& p : mm.equal_range(key)) {……} // 编译失败:pair 不可迭代 

也有人误以为 equal_range 返回的是 std::vector<value_type></value_type>,试图用 .size() 或下标访问 —— 它返回的是 std::pair<iterator iterator></iterator>,没有这些成员。

  • 别对 equal_range 的返回值用 auto& 然后当成容器遍历
  • 别用 std::distance(range.first, range.second) 来“预估”数量再分配 vector —— 虽然可行,但多一次遍历,除非你真需要随机访问
  • 如果只是计数,直接用 mm.count(key),它内部就调了 equal_range,更简洁

真正容易被忽略的是:equal_range 的两个迭代器都属于同一个 multimap 对象,但它们的生命周期完全依赖于容器本身 —— 插入、删除、甚至移动构造 multimap 都可能导致它们失效。别缓存它们太久。

text=ZqhQzanResources