multimap能存重复键是因为其设计目标即支持键重复,插入时不检查键是否存在,直接按序插入;底层虽为红黑树,但比较规则仅依赖严格弱序,相等键被允许并相邻存储。

multimap为什么能存重复键
因为 multimap 的设计目标就是允许键重复——它不像 map 那样在插入时检查键是否已存在,而是直接追加。底层是红黑树,但比较规则只用 判断顺序,不禁止相等键。所以只要两个键 <code>a 和 <code>b 都为 false(即等价),就能并存。
常见误判:以为 multimap 是“带重复的 map”,其实它是独立容器,接口行为也不同——比如 find() 只返回一个迭代器,而 equal_range() 才是查全部匹配项的正解。
插入重复键的正确写法
直接用 insert(),别用 [] 操作符(multimap 不支持下标赋值,编译报错:error: no match for operator[])。
-
mm.insert({key, value});—— 推荐,简洁且类型推导安全 -
mm.insert(std::make_pair(key, value));—— 兼容老标准,但注意std::pair构造可能隐式转换 -
mm.emplace(key, value);—— 避免临时对象,性能略优,尤其对大 value 类型
错误示例:mm[key] = value; → 编译失败;mm.insert(std::pair<int int>(key, value));</int> → 冗余,且易因类型不匹配导致构造失败。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
遍历所有相同键的值
不能靠 find(),它只返回第一个匹配位置;必须用 equal_range() 获取左闭右开区间。
auto range = mm.equal_range(42);
for (auto it = range.first; it != range.second; ++it) {
std::cout << it->second << "\n"; // 只取 value
}
注意:equal_range() 返回 std::pair<iterator, iterator>,不是单个迭代器;若键不存在,range.first == range.second,循环自动跳过,无需额外判空。
性能提示:在大量重复键场景下,equal_range() 是 O(log n + k),k 是该键出现次数;逐个 find() 再递增找下一个会退化成 O(k log n)。
删除指定键的所有元素
用 erase(key) 重载版本,它返回删除个数(size_t),不是迭代器——这点和 map::erase() 不同。
-
mm.erase(42);→ 删除所有键为 42 的节点,返回实际删掉的数量 -
mm.erase(mm.find(42));→ 错!只删第一个,且find()对不存在的键返回end(),擦除end()是未定义行为 - 想删部分?只能手动遍历
equal_range()区间,用erase(iterator)逐个删(注意迭代器失效)
容易忽略:删除后,其他迭代器是否有效?multimap 的 erase 不会使其他迭代器失效(除了被删的那个),但 erase(iterator) 返回的是下一个有效迭代器,而 erase(key) 没有返回迭代器,要继续遍历得重新 equal_range()。

















