On 14 Oct 2003 07:20:15 -0700,
mhpemberton@vodafone.net (Mike
Pemberton) wrote:
[color=blue]
>I'm sure there's a good explanation for this effect, but I get rather
>a strange output from this little test:
>
>#include <iostream>
>#include <list>
>
>int main()
>{
> std::list<int> int_list;
>
> int_list.push_back(1);
> int_list.push_back(2);
> int_list.push_back(3);
> int_list.push_back(4);
>
> std::list<int>::reverse_iterator rev = int_list.rbegin();
> while(rev != int_list.rend())
> {
> std::cout << *rev++ << std::endl;
> int_list.pop_back(); // This line causes a problem.[/color]
The above line erases the element that rev is pointing to! Remember
that a reverse iterator's base iterator is actually the iterator to
the element after the one that dereferences. In any case, the above
line invalidates rev, so you can't legally perform any operations on
it, including comparing it to rend, dereferencing it and incrementing
it.
[color=blue]
> }
> return 0;
>}
>
>Output:
>4
>3
>2
>1
>0
>0
>
>The inclusion of the int_list.pop_back() call seems to cause the two
>additional iterations through the loop that print the two extra zeros.
> If I comment out the int_list.pop_back() line the output is as
>expected, and if i use a different conditional statement such as
>while(! int_list.empty()) the output is also as expected.
>
>Does anyone know why this doesn't work? Are there member functions of
>std::list that shouldn't be used with iterators, reverse-iterators or
>something?[/color]
Yes, any list operation that erases an element invalidates all
iterators to that element. A reverse iterator is a strange beast,
since its base iterator is actually the one after the element it
dereferences to.
Tom