89

この投稿std::vector::reserve()のコメントセクションには、 vs 。の使用に関するスレッドがありますstd::vector::resize()

元のコードは次のとおりです。

void MyClass::my_method()
{
    my_member.reserve(n_dim);
    for(int k = 0 ; k < n_dim ; k++ )
         my_member[k] = k ;
}

に要素を書き込むにはvector、正しいことはstd::vector::resize()、ではなく、を呼び出すことだと思いstd::vector::reserve()ます。

実際、VS2010 SP1のデバッグビルドでは、次のテストコードが「クラッシュ」します。

#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    v.reserve(10);
    v[5] = 2;

    return 0;
}

私は正しいですか、それとも間違っていますか?そして、VS2010 SP1は正しいですか、それとも間違っていますか?

4

5 に答える 5

128

理由には2つの異なる方法があります。

std::vector::reserveメモリを割り当てますが、ベクトルのサイズは変更されません。これは、以前と同じ論理サイズになります。

std::vector::resizeベクトルのサイズを実際に変更し、デフォルト状態のオブジェクトでスペースを埋めます。それらがintの場合、それらはすべてゼロになります。

予約後、あなたの場合、要素5に書き込むために多くのpush_backsが必要になります。それを望まない場合は、サイズ変更を使用する必要があります。

予約に関する1つのこと:次にpush_backを使用して要素を追加すると、予約した容量に達するまで、ベクター内のデータへの既存の参照、イテレーター、またはポインターは引き続き有効です。したがって、1000を予約し、サイズが5の場合&vec[4]、ベクトルに1000個の要素が含まれるまで同じままになります。その後、呼び出すことができ、push_back()動作しますが、以前に保存されたポインタ&vec[4]が無効になる可能性があります。

于 2012-10-23T11:24:03.213 に答える
15

それはあなたが何をしたいかによります。 ;に要素を追加reserveしません。vectorを変更するだけで、要素を追加しても再割り当てされない(たとえば、イテレータが無効になる) capacity()ことが保証されます。すぐに要素を追加します。後で要素を追加する場合(、)、を使用します。後で(またはを使用して)要素にアクセスする場合は、を使用します。したがって、youreは次のいずれかになります。resizeinsert()push_back()reserve[]at()resizeMyClass::my_method

void MyClass::my_method()
{
    my_member.clear();
    my_member.reserve( n_dim );
    for ( int k = 0; k < n_dim; ++ k ) {
        my_member.push_back( k );
    }
}

また

void MyClass::my_method()
{
    my_member.resize( n_dim );
    for ( int k = 0; k < n_dim; ++ k ) {
        my_member[k] = k;
    }
}

どちらを選んだかは好みの問題ですが、引用したコードは明らかに間違っています。

于 2012-10-23T11:28:55.990 に答える
3

ベクトルの現在のサイズよりも小さい数で両方のメソッドが呼び出される場合については、おそらく議論が必要です。

容量よりも小さい番号で電話reserve()をかけても、サイズや容量に影響はありません。

現在のサイズよりも小さい番号で呼び出すresize()と、コンテナはそのサイズに縮小され、余分な要素が効果的に破棄されます。

合計するresize()とメモリが解放されますが、解放されreserve()ません。

于 2015-07-07T21:32:37.820 に答える
2

はい、あなたは正しいです、ルチアンはちょうどタイプミスをしました、そしておそらく彼の間違いを理解するにはあまりにもコーヒーを奪われています。

于 2012-10-23T11:22:35.760 に答える
1

サイズ変更は実際にはベクトル内の要素の量を変更します。サイズ変更によってベクトルが大きくなる場合、新しいアイテムがデフォルトで作成されます。

vector<int> v;
v.resize(10);
auto size = v.size();

この場合、サイズは10です。

一方、reserveは、内部バッファを指定されたサイズに拡張することを要求するだけで、配列の「サイズ」は変更せず、バッファサイズのみが変更されます。

vector<int> v;
v.reserve(10);
auto size = v.size();

この場合、サイズはまだ0です。

したがって、質問に答えるには、そうです。十分なスペースを予約していても、インデックス演算子を使用して初期化されていないメモリにアクセスしています。intはそれほど悪くはありませんが、クラスのベクトルの場合は、構築されていないオブジェクトにアクセスすることになります。

デバッグモードに設定されたコンパイラの境界チェックは、この動作によって明らかに混乱する可能性があります。これが、クラッシュが発生している理由である可能性があります。

于 2012-10-23T11:33:51.163 に答える