I’ve just noticed something about the std::list class in C++ I find curious. Briefly, it concerns the manner in which the list’s iterators work. Consider the following code:
std::list<int> alist;
alist.push_back(0);
alist.push_back(1);
alist.push_back(2);
Obviously enough, this creates a list with three integer elements in it. I can define an iterator to the start of the list and use it to, say, print out the value contained in the first element as follows:
std::list<int>::iterator iter = alist.begin();
std::cout << *iter << std::endl; // Prints "0" to stdout
What I find mildly odd is that if I now decrement the iterator, it “loops around” and ends up pointing at the last element in the list:
--iter;
std::cout << *iter << std::endl; // Prints "2" to stdout
Is this reasonable behaviour for something that’s supposedly implemented as a doubly linked list? I’d quite expect to similar behaviour from the iterator if the list was a circularly linked list, but I find this quite odd.
Are there any practical uses for this iterator behaviour that you’ve used in the past? Are there any gotchas associated with this behaviour that I should keep an eye out for?
(By the way, this happens with gcc 4.7.0 (MinGW). I haven’t tested it with any other version or compiler.)
Decrementing the iterator beyond
begininvokes undefined behaviour. The behaviour you’re seeing is quite likely to be coincidence (indeed, see what happens with a different compiler here).If you want to confirm this, you can simply take a look at the implementation of GCC’s
list; you can usually find the source at/usr/include/c++/4.x.y/bits/stl_list.h.