无序集在一个循环中删除/插入

时间:2014-02-23 15:26:08

标签: c++ c++11 stl

std::unordered_set的值不可变,因为它们都是键和值。如果首先删除,修改然后重新插入其元素,修改std::unordered_set元素的正确方法是什么? erase不会使任何迭代器失效,但insert可能会失效。显而易见的答案是使用迭代器,erase返回。我想,有一种方法可以解决这个问题,即在成功插入之后将循环迭代器重​​置为unordered_set的开头。我想确定,这是唯一的方法。

3 个答案:

答案 0 :(得分:2)

  

erase不会使任何迭代器无效,但insert可能会失效。

您可以随时检查insert是否会这样做:

  

如果由于插入而发生重新散列,则所有迭代器都是   无效。否则迭代器不会受到影响。参考文献不是   无效。仅当新元素数量为时,才会发生重新散列   等于或大于max_load_factor()*bucket_count()。   (来自cppreference

所以,如果你注意重复,你的方法可行。当然,当您检测到重新发送发生时,它会让您知道该怎么做。

您可以通过在循环之前增加集合的容量来降低重新散列的概率。

处理重组的最简单方法是重新开始后重新开始。也许还有其他方法可以处理它,但我不会冒险。


说完所有这些之后,你在这里描述的似乎表明你可能需要另一个容器。如果unordered_set确实是您应用程序的最佳容器,我很可能仍然使用Martin's solution,即使用中间容器。它不那么凌乱,我可以看到发生了什么;我可以推断正确性。

答案 1 :(得分:1)

我认为你最好使用中间容器,比如:

unordered_set<int> original;
...
vector<int> temporary;
for (auto it = original.begin(), itEnd = original.end(); it != itEnd; ) {
    if (...) {
        int newValue = ...;
        auto toDelete = it++;
        original.erase(toDelete);
        temporary.push_back(newValue);
    } else {
       ...
       ++it;
    }
}
original.insert(temporary.begin(), end.begin());

答案 2 :(得分:1)

使用临时unordered_set,您将填充第一个(带有提示),然后将原始集与临时交换。