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.
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: Theend()
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.
cppreference.com states that:
... have the option, but aren't required, to move any resources held by the argument...
It looks like std::move
just is a hint to the library that an optimization by transferring ownership is possible, but it's up to the library whether to do that optimization or not.
That means that you should assume that all pointers to elements are invalidated after the move.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With