2012-01-25 8 views
2

は、私のような何かをやっている:私はデバッグする場合、x.abcが直接割り当て後に正しい見えますが、その後まもなくx.abc内のデータがゴミであるstd :: vector :: operator []から返されるアドレスは何ですか?

struct ABC{ 
int p,q,r; 
}; 

struct X{ 
ABC *abc; 
X(ABC &abc) : abc(&abc) {} 
}; 

std::vector<ABC> vec; 
... //populate vec 

X x(vec[2]); 

。それは私がポインタがローカル変数にあると思うようになっている...しかしvector::operator[]は参照を返すので、それは可能ですか?

+1

もっとコードが必要です。何がvecですか? –

+0

少し更新されました。 –

答えて

7

内部的には、std::vectorは通常、それに含まれる要素の動的配列を保持します。ベクトルのサイズが大きくなりすぎて、古い容量を超えると、新しい配列が割り当てられ、古い要素がコピーされてから古い配列が割り当て解除されます。その結果、その古い配列への参照やポインタは無効になり、使用されると未定義の動作になります。

ポインタをベクターに格納する場合は、ベクターが内部バッファを再割り当てしないようにする必要があります。これを行うには、参照を取得する前にベクターに追加するすべての要素を追加するか、vector::reserveを呼び出して容量が十分に大きいことを確認します。

さらに、インデックスと一緒にvectorオブジェクト自体への参照を格納し、そのインデックスでその要素を毎回ルックアップすることもできます。そうすれば、ベクトルが内部バッファのサイズを変更した場合、毎回ベクトルにインデックスを付け直すので、ポインタがガベージになることはありません。

希望すると便利です。

+2

これは 'std :: vector <>'の代わりに 'std :: deque <>'の良いユースケースです。 – ildjarn

+0

@ildjarn: 'deque'へのポインタを無効にすることができます。おそらく' list'を考えていたと思いますか? –

+0

@Jesse:イテレータは無効になりますが、 'std :: deque <>'への_pointers/references_は、 'deque'へのフロント挿入時またはバック挿入時に無効になりません。なぜなら、既存のものを潜在的に再割当てする必要はないからです。 'std :: vector <>'としての要素は必須です(C++ 11§23.3.3.4/ 1参照)。 – ildjarn

関連する問題