4

STL vector の実装について調べてみました。ベクトル コンテナーは動的配列として実装されます。メソッド clear() は、ベクター内のすべての要素を破棄するために使用されます。これにより、ベクターのサイズが 0 に設定されますが、容量は元のままです。したがって、これを正しく理解していれば、すべての要素はデストラクタと呼ばれていますが、動的に割り当てられたメモリは引き続き使用できます。そして、それを解放するために、次のことができます。

Vec.swap( vector<T>() ); // Capacity = 0.

しかし、スワップを使用せず、クリアしただけだとしましょう。内部実装 (私が間違っている場合は訂正してください) は、次のものとほぼ同じです (非常に単純化された方法で):

// A contained type:
struct C {
    int m;
    C() : m(123){}
};
C * arr = new C[10];  //  Suppose this is the internal array in the container

編集: 上記の new 演算子は実際の実装では使用されず、STL はアロケーターを使用することを理解しています。デストラクタをテストするためのテスト ケースとして new を使用しただけです (これは単なるアナロジーです)。

// Calling clear() :
for(size_t i=0;i<SZ;i++)
    arr[i].~C();  //  Destroying ALL elements  
// some other actions . . .

しかし、容量はまだ 10 であり、メモリにはまだアクセス可能なデータがいくつかあります。

// Accessing the vector at 0:
cout<<arr[0].m<<endl;  //  This prints 123

これは未定義の動作ですか? そうですね、確かに知りたいのですが。

おそらく、デストラクタを呼び出すときに何が起こるか(スタックメモリに関して)をより深く理解していれば、プログラムが関数の範囲外に出たときのデストラクタの呼び出し、またはデストラクタの呼び出しと同じであることがわかります。スコープを出る前は、他のメソッドと同じように見なされ、オブジェクトのスタック メモリは解放されませんか?

免責事項: 上記のコードは、clear() の機能の一部を象徴するために非常に単純化されています。私の調査から得られた結論は、間違っている場合は訂正してください。

4

3 に答える 3

4

std::vector<...>::clear()オブジェクトを破棄し、その内部レコードを適切に設定して、オブジェクトがないことを示すのは正しいことです。破棄されたオブジェクトにアクセスすると、未定義の動作が発生します。データ内のビットは変更されていない可能性がありますが、関連するオブジェクトも同様に破棄され、それらのメモリが他の目的で再利用される可能性があります。

Cを格納するだけintで、デストラクタで何もしない例では、ビットはおそらく変更されていませんが、そのように保証されていません。特に、デバッグの実装では、破棄されたオブジェクトのメモリにガベージを意図的に書き込むために、数サイクルが無駄になる場合があります。

余談ですが、アロケータを介して生メモリをstd::vector<...>使用するnew C[n]のではなく、割り当ておよび割り当て解除します。ただし、それは詳細です。

于 2012-12-29T23:30:08.800 に答える
0

プログラムはメモリ領域を使用します: スタックとヒープ。arr ベクトル アドレスをヒープ メモリに配置しますが、m の値はスタックに存在します。ヒープ メモリを削除する場合は delete [] arr を使用し、アドレス指定されていないメモリを使用する場合は

arr=NULL 構造体はそのように簡単に変更できます

struct C {
int *m;
C(int value) {
    m=new int(value);
}
~C()
{
    delete m;
}

};

于 2012-12-29T23:58:51.587 に答える
0

私の理解が正しければ、主な質問は次のとおりです。

これは未定義の動作ですか?

はい、通常の配列では、前の回答で説明した理由により、未定義の動作があります。ただし、ベクトルのサイズ(容量を超えないように注意してください)std::vector以上のインデックスを使用して の要素にアクセスしようとすると、アクセス演算子は例外をスローします (ただし、関数はそれぞれのデストラクタを呼び出します)。ベクトルの要素であり、その容量は変更されませんが、ベクトルに含まれる要素の数の内部カウントが変更されます)。std::out_of_rangeclear()

于 2012-12-29T23:35:56.753 に答える