2013-03-19 50 views
4

我所遇到的一个问题调用下面的代码:使用std ::双端队列:迭代(在C++ STL),用于搜索和删除某些元件

#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管理deques迭代器的方式中:如果正在擦除的元素更接近deque末尾,则用于指向已擦除元素的迭代器现在将指向NEXT元素,但不是vector::iterator所做的前一个元素。我知道修改循环条件从it != deq.end()it < deq.end()可能可以解决这个问题,但我只是想知道是否有办法在“标准格式”中擦除deque中的某个元素,以便代码可以兼容其他容器类型也是如此。

+2

使用'std :: remove_if'。 – chris 2013-03-19 01:55:58

+0

你可以在分配给std :: remove_if的函数(或函数对象)中执行操作,那么你仍然可以使用std :: remove_if(如@Fraser建议)。我会建议使用通用算法而不是简单循环,因为循环对于您的意图不够清楚。另外,我认为在同一时间修改和遍历容器是危险的。 – 2013-03-20 02:10:22

回答

18

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 
} 

或者为chris提到你可以只使用std::remove_if

10

要使用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可用。

+0

感谢这也是非常有用的信息!但是我有一些额外的操作与要移除的元素相关联,所以@syam的解决方案更适合我。不管怎么说,还是要谢谢你! – 2013-03-19 04:51:35