2012-05-29 1 views
13

Предоставляет ли следующие результаты определенные в терминах стандарта C++?Поведение std :: list: begin(), когда список пуст

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? 

Я могу проверить это на компиляторе, который я использую ... но я бы хотел получить более окончательный ответ.

+0

Я думаю, что это хороший вопрос, потому что это заставило меня думать, хм, на самом деле. Это список ... может быть, это сработает ... (Конечно, это не так) – jcoder

ответ

18

Все стандартные итераторы и контейнерные типы ведут себя так же в связи с этим:

§23.2.1 [container.requirements.general] p6

begin() RETU rns - итератор, ссылающийся на первый элемент в контейнере. end() возвращает итератор, который является значением конца для контейнера. Если контейнер пуст, то begin() == end();

И таблица 107 в §24.2.3 [input.iterators] требует, чтобы в качестве предварительного условия для ++it, it должен быть разыменовываемым, который не относится к пришедшим к конечным итераторам (т.е. то, что вы получаете от end()), как таковые вы «вступая в опасную область неопределенного поведения.

+0

, так что если это был 'myIter -', он будет указывать на толкаемое значение? – balki

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

Итератор имеет такое же значение, как если бы вы его инициализации с myList.end(). Итератор инициализируется положением «взад-вперед». Даже после того, как вы вставляете элемент в список, итератор все еще указывает один на один конец. Если вы увеличиваете его, вы вызываете неопределенное поведение.

UPDATE:

Например, если вы собираете свой фрагмент кода с GCC с -D_GLIBCXX_DEBUG, полученный исполняемый прервет:

/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 
+0

... за исключением того, что, когда у вас есть круглый список, одно-прошлое-конец может дать вам законную начальную точку некоторыми определения. Так вы абсолютно уверены ... или задумались? – omatai

+5

@omatai: 'std :: list <>' не является круговым. – wilx

+0

А-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а-а- круг". D'Oh! Мне нужно вернуться домой ... – omatai