在迭代std :: list时进行擦除 [英] Erasing while iterating an std::list
问题描述
如果我在for
循环中使用iterator
,并且在当前迭代器的迭代器上使用erase
,则for循环应该可以继续正常工作并访问其余的list
元素?>
根据我的阅读,应该是这种情况,并且是list
与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);
}
}
编写该循环的惯用方式是:
for (auto i = list.begin(); i != list.end();) {
if (condition)
i = list.erase(i);
else
++i;
}
您可以对set
,multiset
,map
或multimap
执行相同的操作.对于这些容器,您可以删除一个元素,而不会影响其他元素的任何迭代器的有效性.其他容器,例如vector
或deque
都不是很好.对于那些容器,只有擦除的迭代器之前的元素保持不变.这种差异仅是因为list
将元素存储在单独分配的节点中.删除一个链接很容易. vector
是连续的,取出一个元素会将所有元素移回一个位置.
由于在某些给定条件下擦除了i
处的元素,因此循环中断了.在该调用之后,i
不再是有效的迭代器.然后,您的for
循环递增i
,但是i
无效.地狱随之而来.这就是确切的情况,这就是为什么erase
在删除了内容之后将迭代器返回到元素的原因...,因此您可以继续遍历list
.
您还可以使用 list::remove_if
:
list.remove_if([](auto& i) { return i > 10; });
在lambda中,如果应删除该元素,则返回true.在此示例中,它将删除所有大于10的元素.
If I'm using an iterator
in a for
loop and I use erase
on a current iteration of iterator, the for loop should continue fine and access the rest of the list
elements?
From what I have read, this should be the case and is a primary distinguishing characteristic of list
vs deque
or vector
. For my purposes, a queue
might work but I need this behavior.
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);
}
}
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 vector
or deque
are not so kind. For those containers only elements before the erased iterator remain untouched. This difference is simply because list
s store elements in individually allocated nodes. It's easy to take one link out. vector
s are contiguous, taking one element out moves all elements after it back one position.
Your loop is broken because you erase the element at i
on some given condition. i
is no longer a valid iterator after that call. Your for
loop then increments i
, but i
is not valid. Hell upon earth ensues. This is the exact situation that is why erase
returns the iterator to the element after what was erased... so you can continue traversing the list
.
You could also use 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.
这篇关于在迭代std :: list时进行擦除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!