让我们说我想制作一个对象向量和另一个指向这些对象的指针向量(我不能使用动态内存)。我将采用的方式如下例所示。
#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;
}
}
我认为这应该有效,因为foos
存储了对象的副本,然后我将引用存储到副本中(因为原始foo
将是未定义的,所以我不应该存储参考那个)。但这就是我得到的:
0
36741184
1
0
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
来自pFoos
的第一个数字是错误的。此外,每次都会有大量的变化。我没有看到任何会导致这种未定义行为的东西。有人能告诉我我做错了吗?
答案 0 :(得分:8)
向向量添加项会使以前的所有迭代器无效。如果向量需要重新分配其内部存储,则在向量上调用push_back可能会使从中获取的指针无效。
如果您知道您再也不会再增长向量,那么这将有效:
for (int i = 0; i < 10; i++) {
foos.push_back(Foo(i));
}
for (int i = 0; i < 10; i++) {
pFoos.push_back(&foos[i]);
}
或由罗德里戈评论:
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;
}
答案 1 :(得分:2)
我想这不是一个好的编程方法。向量负责存储对象,它可能会REALLOC内存以获得更大的内存blob ...所以,你的指针不再有效......
答案 2 :(得分:1)
vector::push_back
可以移动元素,这就是地址无效的原因。您可以在开始将向量推送到向量之前调用reserve
将向量的内存预加载到其最终大小,或者您可以等到在完成推送之前完成推送之前的内容。
但是你说你“不能使用动态记忆”。 vector
使用动态内存。