I am traversing an std::list using reverse iterators and erasing some elements from the list using their forward iterators that were obtained when inserting them. A sample program is shown below. I read that deleting elements from a list doesn’t invalidate other iterators except for the ones referring to element that’s deleted. But there’s no mention of reverse_iterators and my program is crashing. Can someone please tell if the usage is incorrect?
What the program is doing is adding an element into the list, storing its iterator, reverse iterating the list and deleting the only element in the list using its stored iterator.
The output is pasted below the code sample.
#include <list>
#include <iostream>
using namespace std;
struct node
{
int data;
list<node*>::iterator iter;
} a;
int main()
{
list<node*> l;
a.data = 1;
l.push_front( &a );
a.iter = l.begin();
list<node*>::reverse_iterator ri = l.rbegin();
while ( ri != l.rend() )
{
cout << (*ri)->data << endl;
list<node*>::reverse_iterator rj = ri;
++ri;
if ( ri == l.rend() )
cout << "before erase: reached end" << endl;
l.erase((*rj)->iter);
if ( ri == l.rend() )
cout << "after erase : reached end" << endl;
else
cout << "after erase : Not reached end" << endl;
}
}
OUTPUT
1
before erase: reached end
after erase : Not reached end
610568524
before erase : reached end
Segmentation fault
Under VS2010 it will throw an exception here, on the first loop pass:
That should give you a general idea what’s going on. You see,
reverse_iteratoris just a wrapper for standard iterator. That said, you should remember that it’s gotbase()member that returns underlying iterator – you don’t have to store it elsewhere, like you do innodestruct.Here’s a great answer to how
reverse_iteratorrelates to theiterator. In your case,rbeginwill be based onbeginiterator. If you remove thebeginfrom the list (which you do, since it has only one element), allreverse_iterators based on thisiteratorwill become invalid. Keeping that in mind you could rewrite your loop the following way: