Stroustrupによると:C ++プログラミング言語:-
「より多くの(またはより少ない)要素に対応するためにベクトルのサイズが変更されると、そのすべての要素が新しい場所に移動される可能性があります。」
ベクトルのサイズが小さいサイズに変更された場合でも、これは当てはまりますか?
ケース1:要求されている新しいサイズが現在のサイズよりも大きい場合、std::vector::capacity()
すべての要素が再配置されます。
ケース2:要求されている新しいサイズが現在よりも小さい場合、std::vector::capacity()
要素の再配置はありません。
スタンダーデスの証拠:
この規格では、効果を次のように定義しvector::resize()
ています。
C++11標準23.3.6.3/12ベクトル容量:
void resize(size_type sz, const T& c);
効果:
if (sz > size())
insert(end(), sz-size(), c);
else if (sz < size())
erase(begin()+sz, end());
else
; // do nothing
@DavidRodríguez-dribeasが正しく指摘しているように、操作のイテレーター無効化ルールは次のstd::vector::insert()
とおりです。
23.3.6.5ベクトル修飾子
1 [insert、push_back、emplace、emplace_back]
備考:新しいサイズが古い容量よりも大きい場合、再割り当てが発生します。再割り当てが発生しない場合、挿入ポイントの前のすべてのイテレータと参照は有効なままです。
基本的に、これは次のことを意味します。新しいコンテナサイズが以前の容量よりも大きくない限り、挿入ポイントの前のすべてのイテレータと参照は影響を受けません。このようなシナリオでは、すべての要素が新しい場所に移動され、元の場所へのポインタ/イテレータが無効になる可能性があるためです。resize()
コンテナの最後にある要素のみを消去/挿入するため[注1]。支配要因は、現在の容量に対して要求されているサイズに要約されます。
したがって、ケース1の結果になります。
ケース2 std::vector::erase()
が呼び出され、この場合の無効化ルールは次のとおりです。
23.3.6.5ベクトル修飾子
イテレータerase(const_iterator position);
3効果:消去の時点またはそれ以降のイテレータと参照を無効にします。
[注1]以降、要素は最後に削除されるだけで、すべての要素を再配置する必要はありません。
...要素は新しい場所に移動される可能性があります。」
移動する可能性があると表示されていることに注意してください。つまり、それはそれがどのようなサイズ変更であるかに依存することを意味します。
ベクトル内のイテレータは、2つの理由で無効になります。イテレータの位置の前に要素が挿入/削除されるか(1)、ベクトルの容量を増やす必要がある場合は、バッファ全体が再配置されます(2)。ここで重要なのは、への変更capacity()
です。
resize()
コンテナの端からのみ挿入/削除するためです。ベクトルが縮小すると、削除される要素を参照するイテレータのみが無効になります。ベクトルが大きくなると、新しいサイズが。よりも小さい場合、イテレータは無効になりませんcapacity()
。新しいサイズが大きい場合、すべてのイテレータは無効になります。
Alsが誤った証拠1を提供したので、ここに正しい引用を追加します。
23.3.6.5ベクトル修飾子
1 [insert、push_back、emplace、emplace_back]
備考:新しいサイズが古い容量よりも大きい場合、再割り当てが発生します。再割り当てが発生しない場合、挿入ポイントの前のすべてのイテレータと参照は有効なままです。
2[消去]
効果:消去の時点以降のイテレータと参照を無効にします。
同様の引用はC++03で見つけることができます。
1resize
挿入または消去のいずれかと同等であることを示す引用符を複製しないようにします。どちらが正しいです。
質問の本文の答えは、「より多くの(またはより少ない)要素に対応するためにベクトルのサイズが変更されると、そのすべての要素が新しい場所に移動される可能性があります。」