2014-10-15 2 views
11

std::list Итераторы имеют очень приятные свойства - они остаются действительными, когда удаляется любой другой элемент, когда добавляется новый элемент и даже когда сменяется 2 списка (Iterator invalidation rules)!std :: list - являются ли итераторы недействительными при движении?

Учитывая поведение кода и что итераторы реализуются по форме указателя на фактический узел, который не изменяется при перемещении списка, я полагаю, что итераторы все еще действительны в новом контейнере, когда std::list перемещается, но также я могу находиться в области UB здесь, обращаясь к недействительной памяти, которая на самом деле имеет «ожидаемое» значение.

std::list<int> l1{3, 2, 1}; 
std::list<int> l2; 

auto it = std::prev(l1.end()); 
std::cout<<l1.size()<<" "<<l2.size()<<" "<<*it<<std::endl; 

l2 = std::move(l1); 
std::cout<<l2.size()<<" "<<*it<<std::endl; 

3 0 1 
3 1 

Гарантирует ли это стандарт, если итераторы остаются в силе, когда std::list перемещаются? Как насчет других контейнеров?

+0

Я видел подобный вопрос раньше. C++ 11 явно не гарантирует недействительности для 'swap', но не для перемещения. Однако они, как правило, имеют такой же эффект. – zch

+1

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

ответ

9

Для контейнеров в целом только swap гарантирует, что итераторы остаются в силе (и указывают на замененные контейнеры).

Для функции std::list функция специального члена splice() гарантирует, что итераторы сохраняют ожидаемое значение.

В целом, создание контейнера из rvalue не дает гарантий относительно итераторов; единственным общим требованием является то, что новый контейнер имеет «то же значение», что и контейнер, из которого он был построен, изначально.

(Вы можете представить себе реализацию отладки итераторов, которые хранят ссылку на контейнер, и эта ссылка станет оборванными после переезда.)

+1

Хорошая точка со ссылкой на контейнер в режиме отладки. Большая часть реализации делает это, чтобы помочь отладить вне диапазона/недействительные итераторы. – Felics

+0

Эта реализация отладки не может удовлетворить требованиям сложности 'swap' (константа). – zch

+0

@zch: Это правда. Я думаю, что итераторы MS используют двойное косвенное действие, чтобы обеспечить эффективные свопы; возможно, что они также останутся действительными при ходах. –

Смежные вопросы