Behaviour of std::list:begin() when list is empty

2019-01-26 06:01发布

问题:

Does the following give defined results in terms of the C++ standard?

std::list<int> myList;
std::list<int>::iterator myIter = myList.begin();    // any issues?
myList.push_back( 123 );
myIter++;                                  // will myIter point to the 123 I pushed?

I can test this out on the compiler I'm using... but I'd like a more definitive answer.

回答1:

All standard iterator and container types behave the same in this regard:

§23.2.1 [container.requirements.general] p6

begin() returns an iterator referring to the first element in the container. end() returns an iterator which is the past-the-end value for the container. If the container is empty, then begin() == end();

And table 107 in §24.2.3 [input.iterators] demands that as a precondition for ++it, it shall be dereferenceable, which is not the case for past-the-end iterators (i.e., what you get from end()), as such you're treading into the dreaded domain of undefined behaviour.



回答2:

std::list<int> myList;
std::list<int> myIter = myList.begin();

The iterator has the same value as if you were initializing it with myList.end(). The iterator is initialized to on-past-the-end position. Even after you push an element into the list the iterator still points one-past-the-end. If you increment it, you are invoking undefined behaviour.

UPDATE:

E.g., if you compile your snippet with GCC with -D_GLIBCXX_DEBUG, the resulting executable will abort:

/usr/include/c++/4.6/debug/safe_iterator.h:236:error: attempt to increment 
    a past-the-end iterator.

Objects involved in the operation:
iterator "this" @ 0x0x7fffc9548fb0 {
type = N11__gnu_debug14_Safe_iteratorINSt9__cxx199814_List_iteratorIiEENSt7__debug4listIiSaIiEEEEE (mutable iterator);
  state = past-the-end;
  references sequence with type `NSt7__debug4listIiSaIiEEE' @ 0x0x7fffc9548fb0
}
zsh: abort (core dumped)  ./listiter


标签: c++ std