C++中multimap怎么存储重复键值对_C++标准库关联容器用法【进阶】

1次阅读

multimap允许重复键且按key排序而非插入顺序;find只返回首个匹配项,需equal_range获取全部;底层红黑树依赖严格弱序,浮点作key需谨慎;等价键插入时新元素置于末尾,保证同key内插入顺序。

C++中multimap怎么存储重复键值对_C++标准库关联容器用法【进阶】

multimap 允许重复键,但必须明确:它不按插入顺序保存,而是按 key 的 operator 排序;插入时不会覆盖,但查找、遍历需用 equal_range循环 find,否则只拿到第一个匹配项。

为什么 insertfind 只返回一个值?

multimap::find() 返回的是任意一个匹配的迭代器(通常是第一个),不是全部。它设计上就只负责“是否存在”,不负责“有多少个”。

  • 想取全部相同 key 的元素,必须用 equal_range(key),它返回 std::pair,左闭右开区间
  • 若只调 find 然后 ++,可能跳到下一个不同 key,中间漏掉同 key 的其他元素
  • count(key) 可快速知道重复数量,但不提供位置信息

multimap 的 key 类型必须支持严格弱序

map 一样,multimap 底层是红黑树,依赖 Compare 函数对象(默认 std::less)做排序和查找。这意味着:

  • 自定义结构体作 key 时,必须提供 operator,或传入自定义比较器,不能只重载 ==
  • 浮点数作 key 极其危险——0.1 + 0.2 != 0.3 会导致看似相同的 key 被当成不同键插入多次
  • 如果真要用浮点,建议转成整数倍(如乘 1000 后取整),或用 std::abs(a - b) 的比较器,但此时 equal_range 行为可能反直觉(因排序依据和相等判断依据不一致)

插入重复 key 时,新节点插入位置有讲究

multimap 保证等价键(!comp(a,b) && !comp(b,a))的插入顺序:新元素总插在已有等价元素的**末尾**(c++11 起稳定,符合“等价即不交换”语义)。

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

  • 这使得用 equal_range 遍历时,同一 key 的多个 value 按插入先后排列
  • 但注意:这个“先后”仅对同一 key 有效;不同 key 之间仍按排序规则穿插,不是 FIFO 队列
  • 若需要全局插入顺序 + 快速按 key 查找,multimap 不够用,得搭配 std::vector 或用 std::unordered_multimap(哈希无序,但插入顺序不保)

别把 multimap 当成万能去重替代品

有人想用 multimap> 存多份指针来“模拟引用计数”,这是错的——multimap 管理的是键值对的生命周期,不是 value 所指对象。

  • erase(iterator) 只销毁那个键值对,不影响其他同 key 的 pair,也不影响 shared_ptr 指向的对象是否被释放
  • 若 value 是裸指针,更危险:多个 key 对应同一地址,erase 一个后其余变成悬垂指针
  • 真正需要“一写多读+自动管理”的场景,该用 std::shared_ptr + 单独容器(如 std::map>),而不是靠 multimap 的重复性

最常被忽略的一点:当你改了 key 的比较逻辑(比如换了比较器),所有已存元素会按新规则重新解释顺序,但 equal_range 的行为依然只基于当前比较器——旧数据没“重排”,只是你查的方式变了。这时候结果可能和预期完全对不上。

text=ZqhQzanResources