Suppose I have a vector of ints,
std::vector numbers;
that is populated with a bunch of values, then I say do this (where an ent
Pointers, references, and iterators to std::vector
elements are guaranteed to stay put as long as you only append to the std::vector
and the size of the std::vector
doesn't grow beyond its capacity()
at the time the pointer, reference, or iterator was obtained. Once it gets resized beyond the capacity()
all pointers, references, and iterators to this std::vector
become invalidated. Note that things are invalidated as well when inserting somewhere else than the end of the std::vector
.
If you want to have your objects stay put and you only insert new elements at the end or the beginning, you can use std::deque
. Pointers and references to elements in the std::deque
get only invalidated when you insert into the middle of the std::deque
or when removing from the middle or when removing the referenced object. Note that iterators to elements in the std::deque
get invalidated every time you insert an element into the std::deque
or remove any element from it.
As all the others have said, when you call .resize()
on a vector your pointers become invalidated because the (old array) may be completely deallocated, and an entirely new one may be re-allocated and your data copied into it.
One workaround for this is don't store pointers into an STL vector. Instead, store integer indices.
So in your example,
std::vector<int> numbers;
int *oneNumber = &numbers[43]; // no. pointers invalidated after .resize or possibly .push_back.
int oneNumberIndex = 43 ; // yes. indices remain valid through .resize/.push_back
When you use a vector's resize() or reserve() function to increase the capacity of the vector, it may need to reallocate memory for the array-backing. If it does reallocate, the new memory will not be located at the same address, so the address stored in oneNumber will no longer point to the right place.
Again, this depends on how many elements the vector is currently being used to store and the requested size. Depending on the specifics, the vector may be able to resize without reallocating, but you should definitely not assume that this will be the case.
Is oneNumber guaranteed to always be pointing at the int at index 43
Yes, this is guaranteed by the standard.
even if say I resize numbers to something like numbers.resize(46)?
No. Once you resize, add, or remove anything to the vector, all addresses and iterators to it are invalidated. This is because the vector may need to be reallocated with new memory locations.
Once you changed the capacity of the vector, the data was copied to another memory block, and the origin data is deleted.
No - the vector can be reallocated when it grows. Usually once the vector doubles in size.
From the C++11 standard
1 Remarks: Causes reallocation if the new size is greater than the old capacity. If no
reallocation happens, all the iterators and references before the insertion point
remain valid. If an exception is thrown other than by the copy constructor, move
constructor, assignment operator, or move assignment operator of T or by any
InputIterator operation there are no effects. If an exception is thrown by the move
constructor of a non-CopyInsertable T, the effects are unspecified.