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

时间:2016-11-13 17:14:56

标签: c++ stl std erase unordered-set

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

我尝试使用g ++ - 6.2.0和clang-3.9的以下代码(虽然在linux上,这是gcc的stdlib)。我认为两者都应该能够通过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

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

发生了什么事?

1 个答案:

答案 0 :(得分:3)

我认为这个循环是错误的:

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

如果执行 erase ,则 it 无效,您无法递增。据推测,它会导致上述行为。

你应该使用这样的东西:

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