使用 std::deque::iterator(在 C++ STL 中)搜索和删除某些元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15490219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:25:56  来源:igfitidea点击:

Using std::deque::iterator (in C++ STL) for searching and deleting certain elements

c++stliteratordeque

提问by William Huang

I have encountered a problem invoking the following code:

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

#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);
}

which resulted in a segmentation fault. After looking into the problem I found that the problem resides in the way the STL manages iterators for deques: if the element being erased is closer to the end of the deque, the iterator used to point to the erased element will now point to the NEXT element, but not the previous element as vector::iteratordoes. I understand that modifying the loop condition from it != deq.end()to it < deq.end()could possibly solve the problem, but I just wonder if there is a way to traverse & erase certain element in a deque in the "standard form" so that the code can be compatible to other container types as well.

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

回答by syam

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

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

All iterators and references are invalidated [...]

Return value : iterator following the last removed element.

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

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

This is a common pattern when removing elements from an STL container inside a loop:

这是从循环内的 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
}

Or as chrismentioned you could just use std::remove_if.

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

回答by Fraser

To use the erase-remove idiom, you'd do something like:

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

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

Be sure to #include <algorithm>to make std::remove_ifavailable.

请务必#include <algorithm>使std::remove_if用。