С++ deque: когда итераторы недействительны

Пожалуйста, поправьте меня, если я ошибаюсь. Спасибо!

insert и erase будут перемещать элементы, но элементы перед позицией, где происходит вставка/стирание, не перемещаются и, следовательно, их итераторы остаются в силе.

push_back и pop_back не делают недействительными любые итераторы.

push_front и pop_front аннулировать все итераторы.

swap не будет перемещать элементы, но почему-то я считаю, что он должен аннулировать итераторы.

Ответы

Ответ 1

push_back() и push_front() определены в терминах insert(). Аналогично, pop_back() и pop_front() определены в терминах erase().

Здесь, что стандарт С++ 03 говорит об аннулировании итератора для insert() (23.2.1.3/1):

Вставка в середине deque аннулирует все итераторы и ссылки на элементы deque. Вставка на обоих концах deque аннулирует все итераторы на deque, но не влияет на действительность ссылок на элементы deque.

Итак, push_front() и push_back() аннулируют итераторы, но ссылки на сами элементы остаются в силе.

Для erase() с обоих концов (23.2.1.3/4):

Стирание в середине deque аннулирует все итераторы и ссылки на элементы deque. Стирание с обоих концов deque делает недействительными только итераторы и ссылки на стираемые элементы.

Итак, pop_front() и pop-back() только аннулируют итераторы/ссылки на элемент в конце, о котором идет речь.

И сказано, что это говорит о swap() для любого стандартного контейнера (23.1/10 "Требования к контейнеру" ):

Функция

no swap() отменяет любые ссылки, указатели или итераторы ссылаясь на элементы смененных контейнеров.

С++ 11 добавляет следующие пояснения относительно того, как ведет себя тетер end() в deque для этих операций. В принципе, итератор с end() должен считаться недействительным после swap() или после стирания последнего элемента в deque:

Операция стирания, которая стирает последний элемент deque, делает недействительным только итератор с последним концом и все итераторы и ссылки на стертые элементы.

Каждый итератор, ссылающийся на элемент в одном контейнере перед свопом, должен ссылаться на тот же элемент в другом контейнере после свопинга. Не указано, будет ли итератор со значением a.end() до того, как swap будет иметь значение b.end() после обмена.

Я думаю, что было бы неплохо прописать код, как если бы эти правила применимы, даже если вы еще не используете компилятор С++ 11.