Erasing while iterating an std::list
c++, list
Solution
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.
Problem
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); } } ```