Search code examples
c++c++11vectorstlmove-semantics

Am I guaranteed that pointers to std::vector elements are valid after the vector is moved?


Considering this example:

std::vector<int> v1 = { 1, 2, 3 };
const int* i = &v1[1];
std::vector<int> v2(std::move(v1));
std::cout << *i << std::endl;

Even though in many STL implementations this will probably work, am I guaranteed by the standard that no reallocations are performed when a std::vector is moved, and the internal buffer backing v2 is the same that used to be the one of v1? I wasn't able to find this information neither on the Internet, nor on the standard itself.


Solution

  • This is LWG open issue 2321 [emphasis mine]

    Moving containers should (usually) be required to preserve iterators

    [...]

    [by Stephan T. Lavavej]
    23.2.1 [container.requirements.general]/10 says that unless otherwise specified, "no swap() function invalidates any references, pointers, or iterators referring to the elements of the containers being swapped. [Note: The end() iterator does not refer to any element, so it may be invalidated. — end note]". However, move constructors and move assignment operators aren't given similar invalidation guarantees. The guarantees need several exceptions, so I do not believe that blanket language like /11 "Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container." is applicable.

    [2014-02-13 Issaquah]

    General agreeement on intent, several wording nits and additional paragraphs to hit.

    STL to provide updated wording. Move to Open.

    Proposed resolution:

    [...]

    no move constructor [...] of a container (except for array) invalidates any references, pointers, or iterators referring to the elements of the source container. [Note: The end() iterator does not refer to any element, so it may be invalidated. — end note]

    So, this is an open issue, with general agreement on its basic solution (pointer shall not be invalidated by moving). However, it isn't officially accepted (yet?) as a defect. As far as I know, all major implementations do not invalidate pointers when move-constructing, and it seems to be a generally (implicitly) provided guarantee.