std::multimap适合存重复键因其底层红黑树支持键重复、自动排序且同键元素保持插入顺序;equal_range高效获取所有匹配键的区间,erase(key)可批量删除,自定义键需确保operator

std::multimap 为什么适合存重复键
因为 std::multimap 明确允许键重复,底层是红黑树实现,自动按 key 排序,且相同 key 的元素按插入顺序(稳定)排列。这和 std::map(拒绝重复键)、std::unordered_multimap(无序、哈希)有本质区别——如果你需要「按 key 范围查 + 允许多值」,std::multimap 是最直接的选择。
插入重复键时要注意的三个细节
插入本身很简单,但容易忽略行为边界:
-
insert()总是成功,返回std::pair中的bool恒为true(因为允许多值),不能靠它判断“是否新增了新键” - 用
emplace()更高效,避免临时对象构造,例如:mm.emplace(42, "hello") - 若批量插入相同 key 的多个值,它们在迭代器遍历时**保持插入顺序**(C++11 起保证),但整个容器仍按 key 排序——也就是说,所有 key=42 的节点会连续出现,且内部有序
用 equal_range 高效查区间内所有重复键
这是处理重复键的核心操作。相比 find()(只返回一个迭代器),equal_range(key) 返回一对迭代器:std::pair,分别指向第一个等于 key 和第一个大于 key 的位置——也就是所有 key 对应值的闭左开右区间。
std::multimapmm; mm.insert({3, "a"}); mm.insert({3, "b"}); mm.insert({5, "c"}); auto range = mm.equal_range(3); for (auto it = range.first; it != range.second; ++it) { std::cout << it->second << "\n"; // 输出 "a", "b" }
注意:lower_bound(key) 和 upper_bound(key) 单独调用也能实现同样效果,但 equal_range 通常一次二分完成,性能更稳。
立即学习“C++免费学习笔记(深入)”;
删除指定 key 的所有值或仅删一个
删除逻辑和查询对称:
-
mm.erase(key)—— 删除所有 key 相等的元素,返回被删数量(size_t) -
mm.erase(it)—— 删除单个迭代器指向的元素(it必须合法且未失效) - 想删某 key 的前 N 个?得手动遍历:
auto r = mm.equal_range(key);然后用std::next(r.first, N)截断并 erase 区间
别用 find() 后直接 erase(it) 来删重复键——它只删第一个匹配项,容易误判“删完了”。
真正麻烦的是:当 key 类型是自定义类时,operator 必须严格符合全序,且 equal_range 依赖它;如果比较逻辑写错,区间可能为空或越界,调试时很难一眼发现。











