Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 307
gd1 Avatar asked Sep 06 '25 03:09

gd1


2 Answers

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.

like image 143
dyp Avatar answered Sep 08 '25 01:09

dyp


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.

like image 41
Anders Abel Avatar answered Sep 08 '25 01:09

Anders Abel