Reputation: 12249
Lets say I wanted to make a vector of objects and another vector of pointers to those objects (I cannot use dynamic memory). The way I would do it is in the following example.
#include <iostream>
#include <vector>
using namespace std;
class Foo {
public:
int bar;
Foo(int x) : bar(x) {
}
};
int main () {
vector<Foo> foos;
vector<Foo*> pFoos;
for (int i = 0; i < 10; i++) {
Foo foo(i);
foos.push_back(foo);
pFoos.push_back(&foos.back());
}
for (int i = 0; i < 10; i++) {
cout << foos[i].bar << endl;
cout << pFoos[i]->bar << endl;
}
}
I think this should work because foos
stores a copy of the object, and then I store the reference to the copy (because the original foo
will be undefined, so I shouldn't store a reference to that). But this is what I get:
0
36741184
1
0
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
The first to numbers from pFoos
are wrong. Furthermore, the large number changes every time. I don't see anything that would cause this undefined behavior. Could someone tell me what I'm doing wrong?
Upvotes: 0
Views: 151
Reputation: 1839
Adding items to a vector invalidates all previous iterators. Calling push_back on the vector may make the pointers you got from it previously invalid if the vector needs to reallocate its internal storage.
If you knew that you were never going to grow the vector again then this would work:
for (int i = 0; i < 10; i++) {
foos.push_back(Foo(i));
}
for (int i = 0; i < 10; i++) {
pFoos.push_back(&foos[i]);
}
or as commented by rodrigo:
foos.reserve(10)
for (int i = 0; i < 10; i++) {
Foo foo(i);
foos.push_back(foo);
pFoos.push_back(&foos.back());
}
for (int i = 0; i < 10; i++) {
cout << foos[i].bar << endl;
cout << pFoos[i]->bar << endl;
}
Upvotes: 8
Reputation: 76498
vector::push_back
can move elements, which is why the addresses aren't valid. You can pre-load the memory for the vector to its final size by calling reserve
before you start pushing things into the vector, or you can wait until you've finished pushing things before you take their addresses.
But you say that you "cannot use dynamic memory". vector
uses dynamic memory.
Upvotes: 1
Reputation: 7347
I guess this is not a good programming approach. The vector is responsible for storing objects and it may REALLOC memory to get bigger memory blobs ... So, your pointer is not valid anymore ...
Upvotes: 2