std::unordered_map行为特性及使用配置相关问题咨询
std::unordered_map 相关问题解答
问题1:已存在相同键时插入新元素,是否一定会覆盖旧元素?
答案是否,具体行为取决于你调用的插入方法:
- 调用
insert()、emplace()这类方法时,不会覆盖已有元素:如果键已存在,插入操作直接失败,返回值会告知你插入结果,原有元素的值不会发生任何修改。 - 调用
[]运算符赋值、insert_or_assign()方法时,会强制覆盖已有元素:不管旧值和新值是否相同,只要键存在,就会直接用新值替换旧值,键不存在的话就新增元素。
问题2:能否让std::unordered_map支持同键存储多个元素?
不需要修改std::unordered_map的默认行为,标准库已经提供了对应的实现方案:
- 直接使用
std::unordered_multimap即可,它的底层实现和std::unordered_map一致,唯一区别就是允许存储多个相同键的元素,天然满足同键多值的需求。 - 如果你只想用std::unordered_map实现,也可以把值的类型声明为容器,比如
std::unordered_map<KeyType, std::vector<ValueType>>,每次插入对应键的元素时,往值对应的vector里追加数据即可。
问题3:插入元素时每次扩容1个单位,和哈希表2倍扩容的逻辑不符是什么原因?
你观察到的“每次加1”是容器存储的元素数量(即size()返回值),不是哈希表的桶(bucket)数量:
- std::unordered_map的扩容指的是桶数量的增加,只有当元素数量达到
桶数 * 负载因子(默认负载因子是1.0)的阈值时才会触发,绝大多数标准库实现都会按2倍或者质数序列扩容桶数,保证均摊O(1)的插入复杂度。 - 单个元素插入只会让元素计数加1,不会每次都触发桶扩容,你混淆了元素计数和桶计数两个不同的指标。
问题4:如何给空的std::unordered_map设置初始大小,避免多次扩容开销?
可以通过两种方式实现:
- 构造容器时直接传入初始桶数:
std::unordered_map<KeyType, ValueType> umap(1024);,提前分配足够的桶空间。 - 调用
reserve()方法:如果提前预知要存储1000个元素,直接执行umap.reserve(1000);即可,容器会自动计算需要的桶数,提前分配空间,保证后续插入1000个元素的过程中不会触发扩容和重哈希操作。reserve()是更推荐的写法,不需要你自己根据负载因子计算需要的桶数,接口更易用。
内容的提问来源于stack exchange,提问作者Algo
相关产品推荐
相关产品推荐

