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

またはロドリゴのコメントによると:

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 に答える