在迭代std :: list时擦除

joh*_*ers 17 c++ list

如果我iteratorfor循环中使用an 并且erase在迭代器的当前迭代中使用,for循环应该继续正常并访问其余list元素?

从我所读到的,这应该是这种情况,并且是listvs deque或者的主要区别特征vector.为了我的目的,一个queue可能工作,但我需要这种行为.

这是我正在考虑的循环:

    std::list<Sequence>::iterator iterator;
    iterator=m_concurrents.begin();
    for (;iterator!=m_concurrents.end();++iterator){
        if (iterator->passes()){
            m_concurrents.erase(iterator);
        }
    }
Run Code Online (Sandbox Code Playgroud)

Dav*_*vid 48

编写该循环的惯用方法是:

for (auto i = list.begin(); i != list.end();) {
    if (condition)
        i = list.erase(i);
    else
        ++i;
}
Run Code Online (Sandbox Code Playgroud)

你可以做同样的事情了set,multiset,map,或multimap.对于这些容器,您可以擦除元素,而不会影响对其他元素的任何迭代器的有效性.其他容器喜欢vectordeque不那么友善.对于那些容器,只有擦除迭代器之前的元素保持不变.这种差异仅仅是因为lists存储元素在单独分配的节点中.一个链接很容易.vectors是连续的,取出一个元素后,将所有元素移回一个位置.

您的循环被破坏,因为您i在某些给定条件下擦除了元素.i在该调用之后不再是有效的迭代器.for然后你的循环递增i,但i无效.地狱般的地狱随之而来.这就是为什么erase在删除之后将迭代器返回到元素的确切情况...所以你可以继续遍历list.

你也可以使用list::remove_if:

list.remove_if([](auto& i) { return i > 10; });
Run Code Online (Sandbox Code Playgroud)

在lambda中,如果要删除元素,则返回true.在此示例中,它将删除大于10的所有元素.

  • @Casey [你错了](http://en.cppreference.com/w/cpp/container/list/erase) (5认同)
  • 这不适用于非C++ 11编译器.擦除成员方法只返回C++ 03中的`void`.将`i = list.erase(i)`更改为`list.erase(i ++)`将修复它. (2认同)
  • 还要考虑`list.erase(std :: remove_if(list.begin(),list.end(),condition),list.end())` (2认同)