Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.

like image 453
omatai Avatar asked May 29 '12 05:05

omatai


People also ask

Is std::list ordered?

std::list::sort. Sorts the elements in ascending order. The order of equal elements is preserved.

Is std::list a doubly-linked list?

std::list is a container that supports constant time insertion and removal of elements from anywhere in the container. Fast random access is not supported. It is usually implemented as a doubly-linked list.

What is std::list in c++?

In C++, the std::list refers to a storage container. The std:list allows you to insert and remove items from anywhere. The std::list is implemented as a doubly-linked list. This means list data can be accessed bi-directionally and sequentially.

Should I use std::list?

Consider using std::list if: You need to store many items but the number is unknown. You need to insert or remove new elements from any position in the sequence. You do not need efficient access to random elements.


2 Answers

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.

like image 187
Xeo Avatar answered Dec 04 '22 20:12

Xeo


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 
like image 34
wilx Avatar answered Dec 04 '22 18:12

wilx