6

我在调用以下代码时遇到问题:

#include<deque>
using namespace std;

deque<int> deq = {0,1,2,3,4,5,6,7,8};

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

这导致了分段错误。在查看问题后,我发现问题在于 STL 管理双端队列迭代器的方式:如果被擦除的元素更接近双端队列的末尾,则用于指向已擦除元素的迭代器现在将指向 NEXT元素,但不是前一个元素vector::iterator。我知道从it != deq.end()to修改循环条件it < deq.end()可能会解决问题,但我只是想知道是否有办法以“标准形式”遍历和擦除双端队列中的某些元素,以便代码可以与其他容器类型兼容也是。

4

2 回答 2

19

http://en.cppreference.com/w/cpp/container/deque/erase

所有迭代器和引用都无效 [...]

返回值:最后一个被移除元素之后的迭代器。

这是从循环内的 STL 容器中删除元素时的常见模式:

for (auto i = c.begin(); i != c.end() ; /*NOTE: no incrementation of the iterator here*/) {
  if (condition)
    i = c.erase(i); // erase returns the next iterator
  else
    ++i; // otherwise increment it by yourself
}

或者正如克里斯提到的那样,您可以使用std::remove_if.

于 2013-03-19T02:02:57.197 回答
11

要使用erase-remove idiom,您可以执行以下操作:

deq.erase(std::remove_if(deq.begin(),
                         deq.end(),
                         [](int i) { return i%2 == 0; }),
          deq.end());

一定要#include <algorithm>提供std::remove_if

于 2013-03-19T02:19:46.947 回答