在迭代期间添加到 std::unordered_set(或 unordered_map)中的元素是否会在迭代期间访问?

Will elements added into a std::unordered_set (or unordered_map) during iteration be visited during the iterations?

本文关键字:unordered 迭代 元素 是否 访问 set 添加 std map      更新时间:2023-10-16

我的代码如下所示:

std::unordered_set<int> ht{1,2,3};
ht.reserve(10000);  // ht will not exceed this size
for(int i = 0; i < n; i++)
{ 
auto j = i;
for(auto it = ht.begin(); it != ht.end(); ++it)
{
// do some stuff
int v = j++;
ht.emplace(v);
}
}

对于内部循环,我想从 ht 的开头循环到结束,但我不希望循环遍历循环中任何新添加的元素。换句话说,上面等同于下面吗?

std::unordered_set<int> ht{1,2,3};
ht.reserve(10000);  // ht will not exceed this size
for(int i = 0; i < n; i++)
{
auto temp = ht;
auto j = i;
for(auto it = ht.begin(); it != ht.end(); ++it)
{
// do some stuff
auto v = j++;
temp.emplace(j);
}
ht = temp;
}

根据我所做的几次运行,它似乎是等效的,但我不知道这是否是未定义的行为,或者它们是否确实是等效的。如果将unordered_set更改为vector,这将不起作用,但似乎前向迭代器有效。

如果ht.reserve(10000); // ht will not exceed this size不存在,或者ht确实超出了预留容量,因此所有前向迭代器都将失效,答案是否会改变?

不,这不安全:

在大多数情况下,容器中的所有迭代器在插入后仍然有效。唯一的例外是当容器的增长强制重新散列时。在这种情况下,容器中的所有迭代器都将失效。

有时它有效,但我认为这对你来说还不够!

No.请参阅std::unordered_set上的 cpp 首选项。

Cppreference.com 具有迭代器失效部分,用于描述迭代器何时失效。在使用std::unordered_set的情况下,当发生重新哈希时,插入是不安全的。

仅当新元素数大于max_load_factor()*bucket_count()时,才会进行重新哈希

而且您无法确定插入元素是否会导致这种情况发生。

在您的示例中,您实际上并没有取消引用迭代器,那么为什么不遍历集合的大小呢?

size_t limit = ht.size();
for (size_t i = 0; i < limit; ++i) {
...
}