How do I remove element pointed to by iterator in a C++ list? why does not this work?
int main()
{
list<int> l;
l.push_back(5);
l.push_back(6);
for(auto &it: l)
{
l.erase(*it);
}
return 0;
}
Why
for(auto &it: l){
l.erase(*it);
}
fails to work:
it
is not an iterator. In a range-based for loop, the variable declared before the colon, the range_declaration, will receive an item in the container, an int
in this case. Since it
will receive an int
, auto
will infer a type of int
resulting in
for(int &it: l){
l.erase(*it);
}
and std::list::erase
requires an iterator. I'm assuming the *
is simply the result of a bit of shotgun debugging to see if dereferencing what was believed to be an iterator helped (it wouldn't).
Side note: You cannot remove an item from a container while iterating the container with a range-based for loop. The magic in the background that implements the for loop looks something like
{
auto cur = container.begin() ;
auto end = container.end();
for ( ; cur != end; ++cur)
{
auto val = *cur;
do_stuff
}
}
If in do_stuff
you remove cur
from the container, ++cur
is invalid. Since cur
's not in the container anymore, you can't use it to advance to the next item in the container. std::list
is very permissive in its iterator invalidation rules. Many containers will fail when the cached end
iterator is invalidated.
How to fix:
The given code appears to be trying to empty all the items in the list
. std::list::clear
does that for you with a single function call.
If you want to release a particular element or select elements by value, you should use std::list::remove
or std::list::remove_if
in conjunction with std::list::erase
eg:
l.erase(l.remove(5), l.end()); // remove all elements containing the number 5
if you want to remove the first item, std::list::pop_front
. To remove the last item, std::list::pop_back
. If you want to remove any other element by position, you must have a valid iterator for that position (If you do not already have one, see std::advance
) and then call erase
. Note that if you're having to iterate a lot to find items to remove, std::list
may not be the right container for this job because list
iteration is expensive and quickly eliminates the benefits of cheap insert and removal.