C++ 在迭代 std::list 时擦除
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16269696/
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
Erasing while iterating an std::list
提问by johnbakers
If I'm using an iteratorin a forloop and I use eraseon a current iteration of iterator, the for loop should continue fine and access the rest of the listelements?
如果我iterator在for循环中使用in并且我erase在迭代器的当前迭代中使用,那么 for 循环应该继续正常并访问其余list元素?
From what I have read, this should be the case and is a primary distinguishing characteristic of listvs dequeor vector. For my purposes, a queuemight work but I need this behavior.
从我读到的内容来看,情况应该如此,并且是listvsdeque或的主要区别特征vector。出于我的目的, aqueue可能会起作用,但我需要这种行为。
Here is the loop I am considering:
这是我正在考虑的循环:
std::list<Sequence>::iterator iterator;
iterator=m_concurrents.begin();
for (;iterator!=m_concurrents.end();++iterator){
if (iterator->passes()){
m_concurrents.erase(iterator);
}
}
回答by David
The idiomatic way to write that loop would be:
编写该循环的惯用方法是:
for (auto i = list.begin(); i != list.end();) {
if (condition)
i = list.erase(i);
else
++i;
}
You can do the same thing with a set, multiset, map, or multimap. For these containers you can erase an element without affecting the validity to any iterators to other elements. Other containers like vectoror dequeare not so kind. For those containers only elements before the erased iterator remain untouched. This difference is simply because lists store elements in individually allocated nodes. It's easy to take one link out. vectors are contiguous, taking one element out moves all elements after it back one position.
你可以用set, multiset, map, 或做同样的事情multimap。对于这些容器,您可以删除元素而不影响其他元素的任何迭代器的有效性。其他容器喜欢vector或deque不那么友好。对于那些容器,只有被擦除迭代器之前的元素保持不变。这种差异仅仅是因为lists 将元素存储在单独分配的节点中。去掉一个链接很容易。vectors 是连续的,取出一个元素会将其后的所有元素移回一个位置。
Your loop is broken because you erase the element at ion some given condition. iis no longer a valid iterator after that call. Your forloop then increments i, but iis not valid. Hell upon earth ensues. This is the exact situation that is why erasereturns the iterator to the element after what was erased... so you can continue traversing the list.
您的循环被破坏,因为您i在某个给定条件下删除了元素。i在该调用之后不再是有效的迭代器。您的for循环然后递增i,但i无效。人间地狱接踵而至。这就是为什么erase在擦除后将迭代器返回到元素的确切情况......所以你可以继续遍历list.
You could also use list::remove_if:
您还可以使用list::remove_if:
list.remove_if([](auto& i) { return i > 10; });
In the lambda, return true if the element should be removed. In this example, it would remove all elements greater than 10.
在 lambda 中,如果应该删除元素,则返回 true。在这个例子中,它将删除所有大于 10 的元素。
回答by Frank Hou
for (auto i = list.begin(); i != list.end(); ++i) {
if (condition) {
list.erase(i);
--i;
}
}
回答by Jayhello
If you just want to use for iterator, you can use it this way, for example:
如果你只是想用于迭代器,你可以这样使用它,例如:
list<int> lst{4, 1, 2, 3, 5};
for(auto it = lst.begin(); it != lst.end();++it){
if ((*it % 2) == 1){
it = lst.erase(it); erase and go to next(erase will return the next iterator)
--it; // as it will be add again in for, so we go back one step
}
}
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
But erase in whileiterator will be more clear:
但是在while迭代器中擦除会更清楚:
list<int> lst{4, 1, 2, 3, 5};
auto it = lst.begin();
while (it != lst.end()){
if((*it % 2) == 1){
it = lst.erase(it);// erase and go to next
} else{
++it; // go to next
}
}
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
You can also use member function remove_if:
也可以使用成员函数remove_if:
list<int> lst{4, 1, 2, 3, 5};
lst.remove_if([](int a){return a % 2 == 1;});
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
Or use std::remove_ifconbine with erasefuntion:
或使用std::remove_if结合erase功能:
list<int> lst{4, 1, 2, 3, 5};
lst.erase(std::remove_if(lst.begin(), lst.end(), [](int a){
return a % 2 == 1;
}), lst.end());
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
You can also reference to this question: Removing item from vector, while in C++11 range 'for' loop?
您还可以参考这个问题: Removing item from vector, while in C++11 range 'for' loop?

