ベクトルがより多くのメモリを必要とし、メモリを再配置するとき、ポインタには何が起こりますか?

ベクトルがより多くのメモリを必要とするとき、どこかでメモリを再割り当てします、私はまだどこにいるのかわかりません!ポインタが無効になった場合、これに関する良い説明はありますか?

彼らがどこに行くのか、私のコンテナはどうなるの? (リンクされていないもの)

9
Protip:ポインタではなくインデックスを使用します。
追加された 著者 Kos,
@zermの再配置はイテレータも無効にします。ちなみに、 * ip はもちろん、 ip だけを無効にしません。
追加された 著者 Christian Rau,
@Michael私はちょうど ip が指すオブジェクトを無効にしないことを意味しましたが、ポインタを意味します。もちろん、無効なポインタの逆参照も無効です。私はちょうど私が行ってはいけないはずだったと思う。私は式 * ip を参照していなかったと言えますが、式の値は言います。
追加された 著者 Christian Rau,
これを実証するいくつかのコードは役に立ちます...
追加された 著者 Marc B,
@ChristianRau、ああ、それは私の2番目の推測でした(私はあなたがまだ最初の部分を言いましたと思うhairsplittingwise、攻撃する傾向があります:))
追加された 著者 Michael Krelin - hacker,
ああ、どこかで * ip の値を保存すると有効だろうか?
追加された 著者 Michael Krelin - hacker,
@ChristianRauポインタとしての ip が無効な場合、式として * ip を有効にする方法はありますか? :)
追加された 著者 Michael Krelin - hacker,
@ChristianRauはい、申し訳ありませんが、あなたは両方の面で絶対に正しいです。
追加された 著者 zerm,
私はこれが問題かもしれないと思う: std :: vector foo(10); int * ip =&foo.front(); 再割り当てによって * ip が無効になる可能性があります。しかし、std :: vectorをこの方法で乱用すべきではありません。イテレータを使用する。
追加された 著者 zerm,

3 答え

Short answer: Everything will be fine. Don't worry about this and get back to work.

Medium answer: Adding elements to or removing them from a vector invalidates all iterators and references/pointers (possibly with the exception of removing from the back). Simple as that. Don't refer to any old iterators and obtain new ones after such an operation. Example:

std::vector v = get_vector();

int & a = v[6];
int * b = &v[7];
std::vector::iterator c = v.begin();
std::advance(it, 8);

v.resize(100);

現在、 a b c b c 間接参照することはできません。

Long answer: The vector keeps track of dynamic memory. When the memory is exhausted, it allocates a new, larger chunk elsewhere and copies (or moves) all the old elements over (and then frees up the old memory, destroying the old objects). Memory allocation and deallocation is done by the allocator (typically std::allocator), which in turn usually invokes ::operator new() to fetch memory, which in turn usually calls malloc(). Details may vary and depend on your platform. In any event, any previously held references, pointers or iterators are no longer valid (presumably because they refer to the now-freed memory, though it's not specified in the standard why they're invalid).

15
追加された
私はあなたが実際の質問に答えるとは思わない、それは再配置の前に取得されたベクトルデータへのポインタに関するものだった。
追加された 著者 Macmade,
Cの観点から、これを見てください: gist.github.com/1392643 もちろん、それはこの方法でコード化するのは危険です。しかし、私はOPがベクトルの使用について混乱していると思うし、ベクトルを使用するときに、そのような種類のコードがOKかどうか実際に尋ねていました...
追加された 著者 Macmade,
それは私がアップダウンに私のdownvoteを回すことを喜んで言った。私はあなたがベクトル・エントリーからポインターを(そしておそらくストアする)危険な理由を説明する必要があると思います。基本的には、ポインタを純粋なCで動的配列エントリに格納してから、その配列を再割り当てするのと同じです。しかし、IMHOあなたはそれについて言及しなければなりません、質問は実際にこれについてでした。
追加された 著者 Macmade,
効果的に、私はダウン投票者ですが、個人的なことはありません。私はCのプログラマーであり、私はC ++でかなり錆びていることを知っています。この答えはうまく形成され、重要なことなどを説明しますが、質問は指針に関するものでした。このような場合にポインタを使用すべきではないとしても、C ++では、参照、ベクトル内部などについては言及するのではなく、なぜ言及すべきかと思います。あなたには明らかかもしれませんが、そうではないと思います質問を投稿した人のために。ですから、質問そのものに焦点を当てて、なぜその人が実際にこれを求めているのか理解しようとしてください。
追加された 著者 Macmade,
@ MichaelKrelin-hacker:OPの質問は、実装の詳細(彼女は再配分の詳細について懸念している)について気楽に遊ぶことができ、実際には心配することは何もありません。長い回答は無効化の理由を説明する詳細を提供するので、すべての拠点がカバーされることを願っています。
追加された 著者 Kerrek SB,
@Macmade:もちろんですが、これは実際には参照を格納するのと本質的に同じです: int&a = v [6]; int * b =&v [7]; v.resize(100); a b は無効です。 &a はポインタであり、 * b は両方とも同じ問題を抱える参照です。私はポストを更新しました!
追加された 著者 Kerrek SB,
@マクマード:いいえ心配、あなたの反対は認めています。私は実際にOPを理解するのに苦労しています(誰もOP自身を伝えていない)。さらなる解明が必要な場合は、私の答えを修正することができれば幸いです。ポインタと参照は本質的に無効化の目的のために交換可能です(私の前のコメントを参照してください)。しかし、経験によって、時には私が何を意味するのかを知っていてはならないことを尋ねることを求めるSOの質問があり、これがそのような状況の1つであると感じています。それは私のテイクだけど!
追加された 著者 Kerrek SB,
ダウンホッター、あなたの反対を説明するために気をつけますか?
追加された 著者 Kerrek SB,
@ MichaelKrelin-hacker:ポインタと参照は本質的に同じです:ポインタを逆参照し、参照を取得し、参照のアドレスを取得し、ポインタを取得します。したがって、「参照は無効になりました」にはすべての情報が含まれています。私は安全であるために明示的に "ポインタ"を追加しました。
追加された 著者 Kerrek SB,
私はまだ "すべてがうまくいく"ビットを少し誤解を招くことがわかります。 :X私は、 "私はベクトル要素へのポインタを持っている"という文脈で、 "それは良い"とは言えないと思います。
追加された 著者 GManNickG,
すべてがうまくいく、実際には知識のために知りたいですが、mediamと長い回答に感謝します。私はすべての回答を受け入れることができればいいと思います。
追加された 著者 Synxmax,
ああ。そして、いいえ、私はdownvoterではない:)
追加された 著者 Michael Krelin - hacker,
しかし...「すべてがうまくいく」とはどういう意味ですか?私は、OPがベクトルデータを指し示すポインターを使うと考えましたか?彼がアイデアを持っていれば、すべてがうまくいくと思う。
追加された 著者 Michael Krelin - hacker,
まあ、私はまだdownvoter(私はMacmadeと仮定して)あなたがポインタで何が起こるかを言及すべきであることに同意します。それとも少なくとも私はむしろすべてがうまくいくと言って避けるだろうというような言葉を持っている。つまり、短期的な答えが関心を高める唯一の部分です。
追加された 著者 Michael Krelin - hacker,

vector からアイテムを追加または削除すると、そのアイテム内のすべてのイテレータ(およびポインタ)が無効になります。アイテムへのポインタをベクトルに格納する必要がある場合は、ベクトル const を作成するか、別のコンテナを使用します。

ベクトルがどこに物を格納するかはあなたにとって重要ではありません。あなたは何もする必要はありません。仕事をさせてください。

5
追加された

std :: vector を使用すると、クラスはメモリ割り当て、ポインタ、サイズ変更などのすべての詳細を処理します。

vector クラスはイテレータと参照によってその内容を公開します。再配置が必要な場合があるため、ベクターの突然変異はイテレーターと参照を無効にする可能性があります。

vector クラスは、その要素を連続したメモリ位置に格納することを保証するので、ポインタを使用してコンテンツにアクセスすることは有効です。明らかに、リストのどのような突然変異も、潜在的な再配置のために、その内容へのポインタを無効にする可能性があります。したがって、ポインタを使用して要素にアクセスした場合、そのポインタを無効にしておかなければなりません。つまり、参照と同じようにコンテンツへのポインタにも同じ規則が適用されます。

ベクター内の項目への参照を維持し、この参照が突然変異後でも有効であるようにするには、項目へのポインタまたは参照ではなく、索引を覚えておく必要があります。その場合、ベクトルの最後に追加することは完全に安全で、インデックス値は引き続き同じ要素を参照します。

4
追加された
問題は、既存のベクターデータへのポインタはどうだったのでしょうか?ベクトル内部についてではありません。
追加された 著者 Macmade,
確かに...その特定のケース、そしてポインタを使用するときに起こりうる問題、IMHOを説明することがうれしいです。
追加された 著者 Macmade,
@Davidあなたが知る必要があることは、ほとんどの場合、データが連続して格納されていることです(そして、あなたがいつも知っている必要はありません)。それはあなたが常に知っている事実です(標準で作業しているC ++)。私は間違いなく、標準がその行動を保証しているときに何らかの虐待を呼び出すことはありません。リファレンスへのポインタを作成するのは悪いことですが、それは決して悪用されません。
追加された 著者 Christian Rau,
@Macmadeあなたはベクトルの内部へのポインタを保持するつもりはありません。すぐにそれを行うと、ベクトル内部について知る必要があります。それでは、内部へのポインタを保持し始めると、内部以外のものについてはどのように質問することができますか?
追加された 著者 David Heffernan,
@WillBickfordあなたが参照を悪用する場合のみ。
追加された 著者 David Heffernan,
@ウィルビックフォードビーナスの有名な言葉の一部から足を吹き飛ばしている。
追加された 著者 David Heffernan,
私は&vect.front()をいくつか使用します。 OpenGL頂点を std :: vector 内に格納し、それを処理します。しかし、最終的にOpenGL関数の中には float * が必要なものがありますので、&vect.front()に渡してください。
追加された 著者 zerm,
@Davidこの回答が主張しているにもかかわらず、私の主張はあなたがアクセス権を持っているということでした。
追加された 著者 Will Bickford,
&vect [0] ...を使用して内部ポインタにアクセスできます。
追加された 著者 Will Bickford,