Does std::move() invalidate iterators?

2.6k Views Asked by At

Consider the following program:

struct list_wrapper
{
    std::vector<int>    m_list;
};

int main()
{
    std::vector<int> myList { 1, 1, 2, 3, 5 };

    const std::vector<int>::iterator iter = myList.begin();

    list_wrapper wrappedList;
    wrappedList.m_list = std::move(myList);

    // Can I still dereference iter?

    return 0;
}

After the call to std::move(myList), does iter now point to a valid item inside wrappedList.m_list, or do move constructors/assignments invalidate all iterators?

2

There are 2 best solutions below

0
On

No, they should not get invalidated after a move operation.

23.3.6.5/1

all iterators and references before the point of insertion are unaffected, unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)

2
On

After http://en.cppreference.com notes (emphasis mine):

After container move assignment (overload (2)), unless elementwise move assignment is forced by incompatible allocators, references, pointers, and iterators (other than the end iterator) to other remain valid, but refer to elements that are now in *this. The current standard makes this guarantee via the blanket statement in §23.2.1[container.requirements.general]/12, and a more direct guarantee is under consideration via LWG 2321

Notes

As hvd have rightly pointed out there is at least once case where the move assignent is forced to invalidate iterators - when the new container has incompatible allocator.

As Ben Voigt noted there is a broader discussion in this topic over here and it actually already covers the c++11 aspects of the question...