c++ - unordered_set::erase(pos) 是否保留元素的顺序?

标签 c++ stl std erase unordered-set

我在 C++14 的标准中读到,当使用 unordered_seterase(iterator pos) 时,元素的顺序被保留。

我用 g++-6.2.0 和 clang-3.9 尝试了以下代码(不过在 linux 上,这个 gcc 的标准库)。两者都应该能够通过 C++14 规范来处理,我认为:

#include <unordered_set>
#include <iostream>
using std::unordered_set; using std::cout;

// output
template<typename Elem, typename Comp>
std::ostream& operator<<(std::ostream&os, const unordered_set<Elem,Comp>&data) {
    for(auto &e : data) { os << e << ' '; } return os << '\n'; }

int main() {
  unordered_set<int> nums{ 1,2,3,4,5,6,7,8,9,10 };
  cout << nums; // MSVC: 9 1 2 3 4 5 6 7 8 10
  for(auto it = nums.begin(); it!=nums.end(); ++it) {
    if(*it % 2 == 0) {
      nums.erase(it);
    }
  }
  cout << nums; // MSCV: 9 1 3 5 7
}

是的,元素的顺序是任意的。这里 MSVC++ 19.00 有 9 1 2 3 4 5 6 7 8 10。在删除所有偶数元素后,剩余元素的顺序仍然相同 9 1 3 5 7

尽管使用 g++ 和 clang++,我得到了一个完全错误的输出

10 9 8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1

这似乎表明元素的顺序在调用之间未保留但只是......我不知道。

这是怎么回事?

最佳答案

我想这个循环是错误的:

for(auto it = nums.begin(); it!=nums.end(); ++it) {
    if(*it % 2 == 0) {
        nums.erase(it);
    }
}

如果执行了erase,那么就会失效,你不能增加它。据推测,它会导致上述行为。

你应该使用这样的东西:

for(auto it = nums.begin(); it!=nums.end();) {
    if(*it % 2 == 0) {
        nums.erase(it++);
    } else {
        ++it;
    }
}

关于c++ - unordered_set::erase(pos) 是否保留元素的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40576583/

相关文章:

c++ - 为什么 C++17 中的 std::variant 允许 std::variant<int, const int>

c++ - 底层 STL:在没有新 vector 的情况下将 std::vector 连接到自身

c++ - std::vector 使用成员变量排序

c++ - 定义一个内部有结构的 map

c++ - STL 代码 typedef typename value_type、size_type 等。这些是如何工作的?

c++ - 在 map 上打印 vector

c++ - 到底什么时候检查 std::ifstream::good() ?

c++ - 从方法而不是自身调用内联 friend

c++ - 不加限定地调用命名空间中的函数

C++与嵌套私有(private)类的友元