0

假设我想创建一个对象向量和另一个指向这些对象的指针向量(我不能使用动态内存)。我会这样做的方式是在下面的例子中。

#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是错误的。此外,大数字每次都在变化。我没有看到任何会导致这种未定义行为的东西。有人可以告诉我我做错了什么吗?

4

3 回答 3

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]);
}

或如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;
}
于 2012-11-12T21:45:37.493 回答
2

我想这不是一个好的编程方法。该向量负责存储对象,它可能会重新分配内存以获得更大的内存块......所以,你的指针不再有效......

于 2012-11-12T21:47:04.790 回答
1

vector::push_back可以移动元素,这就是地址无效的原因。您可以在开始将内容推入向量之前通过调用将向量的内存预加载到其最终大小reserve,或者您可以等到完成推入内容后再获取它们的地址。

但是你说你“不能使用动态内存”。vector使用动态内存。

于 2012-11-12T21:48:54.553 回答