c++ - 为什么 std::unordered_set 重新散列,即使负载因子限制没有被打破?

标签 c++ hash stl unordered-set

根据 cppreference ,

Rehashing occurs only if the new number of elements is greater than max_load_factor()*bucket_count().

此外,[unord.req]/15有类似的规则:

The insert and emplace members shall not affect the validity of iterators if (N+n) <= z * B, where N is the number of elements in the container prior to the insert operation, n is the number of elements inserted, B is the container's bucket count, and z is the container's maximum load factor.

但是,请考虑以下示例:

#include <unordered_set>
#include <iostream>

int main()
{
    std::unordered_set<int> s;
    s.emplace(1);
    s.emplace(42);
    std::cout << s.bucket_count() << ' ';
    std::cout << (3 > s.max_load_factor() * s.bucket_count()) << ' ';
    s.emplace(2);
    std::cout << s.bucket_count() << ' ';
}

使用 GCC 8.0.1,它输出

3 0 7

这意味着在放置 2 之后,虽然新的元素数量 (3) 大于 max_load_factor()*bucket_count(),但会发生重新散列。 (注意第二个输出是 0)。为什么会这样?

最佳答案

您混淆了 bucket_count() 已随迭代器失效而更改的事实。迭代器仅在重新散列的情况下无效,如果新的元素数量小于或等于 max_load_factor()*bucket_count()(顺便说一句,如果 size()>max_load_factor ()*bucket_count() 重新散列可以发生,但不是必须发生)。

因为在您的示例中不是这种情况,所以没有发生重新散列并且迭代器仍然有效。但是,必须增加桶数以容纳新元素。

我用 Mac OSX 的 clang 做了一些实验(扩展你的代码),即使在 rehash(size()) 之后迭代器仍然有效(它确实改变了元素的桶关联,直接测试遍历存储桶并打印其内容)。

关于c++ - 为什么 std::unordered_set 重新散列,即使负载因子限制没有被打破?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49333414/

相关文章:

c++ - vectorS 的单个迭代器

c++ - 这个链表函数有什么问题?

c++ - 如何在不放置任何物理依赖项的情况下指定 Makefile 目标构建顺序?

c++ - 与复合物体的圆碰撞

security - 为什么 SHA-1 哈希函数的最大消息大小 (2^64) - 1 位?

javascript - 如何在 JavaScript 中转换 MD5 密码的 Base64 编码

c++ - 在 C++ 中反转集合的内容

c++ - 如果 std::vector::insert(pos, value) 的位置无效怎么办?

perl - 如何制作 Perl 哈希引用的浅拷贝?

c++ - 在 STL 容器中使用模板类