When I do:
for(i=0; i
s
When you do vectorA.push_back
you may cause that vector to reallocate itself to increase capacity, which means all its contents are moved, which means any pointers to its contents that you have saved are made invalid.
Maybe you want to rethink the whole idea of storing pointers to elements of a vector.
If you can't drop the whole idea of storing pointers, but you know the required size in advance, you could use reserve before the loop:
vectorA.reserve(size);
for(i=0; i<size; i++){
//create objectA here
vectorA.push_back(objectA);
pvectorA.push_back(&vectorA[i]);
}
In this version, the pointers are valid until you either grow vectorA further or destroy it.
Read the documentation of std::vector::push_back
First the description:
Adds a new element at the end of the vector, after its current last element. The content of val is copied (or moved) to the new element.
This effectively increases the container size by one, which causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity.
Then about validity of iterators:
If a reallocation happens, all iterators, pointers and references related to the container are invalidated.
So, when you add an object to the vector, all the pointers pointing to objects in that vector may become invalid - unless you've guaranteed that the vector has enough capacity
with std::vector::reserve
.
Invalid means that the pointer no longer points to a valid object and dereferencing it will have undefined behaviour.
In the latter code, you never add objects to the pointed-to vector after you've stored the pointers, so the pointers are valid.
When you push elements into vectorA
it will occasionally get full, and have to relocate its objects to a larger memory block. That will change the address of each element.
If pvectorA
has stored pointers to the elements' original position, those pointers will still point to the old positions even after the vectorA
elements have been moved to a new location.
This is because the vector reallocated its internal storage when it grows beyond its current capacity; after the reallocation, the address of elements may have changed.
You can avoid reallocation by reserving a big enough storage beforehand:
vectorA.reserve(size);
//vectorB.reserve(size); // this would not hurt either
for(i=0; i<size; i++){
//create objectA here
vectorA.push_back(objectA);
pvectorA.push_back(&vectorA[i]);
}
One final note: if you can use C++11, emplace_back
constructs your object in place, hence, without copying.
If you want a sequence container with constant-time insertion and no invalidation of iterators pointing to other elements, use a std::list. Note however that std::vector is often the fastest data structure to use (in some cases, you need a pre-sorted std::vector). One prominent reason for this is that arrays are more cache friendly than e.g. trees or linked lists.
When you use push_back
to add an element to a vector, it is copied into the vector. The means that, in the first example, vectorA
contains a copy of objectA
, and objectA
goes out of scope and gets deleted right after the closing brace. This means that the pointer in pvectorA
is pointing at at an address that doesn't necessarily contain objectA
any more.
Your second example shouldn't work, because objectA
has gone out of scope after the first loop, so I can't help you there.