11

std::list iterators have some very nice properties - they remain valid when any other element is removed, when a new element is added and even when 2 lists are swapped (Iterator invalidation rules)!

Considering following code behaviour and that the iterators are implement by a form of pointer to the actual node which doesn't change when the list is moved, my guess is that the iterators are still valid in the new container when a std::list is moved, but also I can be in the UB area here by accessing invalid memory which actually has the "expected" value.

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

Is it guaranteed by the standard if the iterators remain valid when std::list is moved? What about other containers?

Community
  • 1
  • 1
Mircea Ispas
  • 18,498
  • 26
  • 109
  • 202
  • I've seen similar question before. C++11 explicitly guarantees no invalidation for `swap`, but not for moving. They usually have the same effect, though. – zch Oct 15 '14 at 09:28
  • 1
    I would say that they may be invalidated with different allocator. – Jarod42 Oct 15 '14 at 09:38

1 Answers1

9

For containers in general, only swap guarantees that iterators remain valid (and point into the swapped containers).

For std::list, the special member function splice() guarantees that iterators retain their expected meaning.

In general, constructing a container from an rvalue doesn't make guarantees about iterators; the only general requirement is that the new container has the "same value" as the container it was constructed from had originally.

(You can imagine debug iterator implementations that store a reference to the container, and that reference would become dangling after a move.)

Kerrek SB
  • 428,875
  • 83
  • 813
  • 1,025
  • 1
    Good point with the reference to the container in debug mode. Most implementation do that to help debugging out of range/invalid iterators. – Mircea Ispas Oct 15 '14 at 09:33
  • This debug implementation couldn't possibly meet `swap` complexity requirement (constant). – zch Oct 15 '14 at 09:34
  • @zch: That's true. I think MS iterators use double indirection to allow efficient swaps; it's possible that they would also remain valid under moves. – Kerrek SB Oct 15 '14 at 09:37