35

次のコードスニペットについて考えてみます。

#include <vector>
using namespace std;

void sub(vector<int>& vec) {
    vec.push_back(5);
}

int main() {
    vector<int> vec(4,0);
    sub(vec);
    return 0;
}

「vec」に「sub」関数に5を格納するスペースが残っていないと仮定すると、新しいメモリはどこに割り当てられますか?

サブ関数のスタックフレームでは?その場合、5はサブ関数の最後で削除されます。ただし、メイン関数のスタックフレームは、その時点でサブ関数のスタックフレームがスタックの一番上にあるため、大きくすることはできません。
std :: vectorは、ヒープ上の要素にメモリを割り当てますか?しかし、どのようにしてそのヒープメモリを解放するのでしょうか。スタック上のローカルベクトルの場合、ベクトルを含む関数のスタックフレームは、削除されることをベクトルに通知せずに、最終的に削除されますか?

4

4 に答える 4

45

std :: vectorは、ヒープ上の要素にメモリを割り当てますか?

はい。または、より正確には、建設時に渡すアロケータに基づいて割り当てます。指定しなかったため、デフォルトのアロケータを取得します。デフォルトでは、これはヒープになります。

しかし、どのようにしてそのヒープメモリを解放するのでしょうか。

スコープ外になったときにデストラクタを介して。(スコープ外になるベクトルへのポインターは、デストラクタをトリガーしないことに注意してください)。しかし、値を渡した場合はsub、新しいコピーを作成します(後で破棄します)。次に、5はそのコピーにプッシュバックされ、コピーはクリーンアップされ、インのベクターはmain変更されません。

于 2012-04-28T18:46:49.760 に答える
21

STL内のすべてのコンテナーは、テンプレート引数でパラメーター化されます。通常、最後の引数はAorAllocatorと呼ばれ、デフォルトstd::allocator<...>...は、コンテナー内に格納されている値のタイプを表します。

Allocator、メモリを提供し、このメモリ領域の要素を構築/破棄するために使用されるクラスです。アロケータを構築したプールから、またはヒープから直接メモリを割り当てることができます。デフォルトでstd::allocator<T>は、は単純なラッパーである::operator newため、推測どおりにヒープにメモリが割り当てられます。

メモリはオンデマンドで割り当てられ、少なくともvector'sデストラクタが呼び出されたときに割り当てが解除されます。C ++ 11ではshrink_to_fit、メモリをより早く解放することも導入されています。最後に、ベクトルが現在の容量を超えると、新しい(より大きな)割り当てが行われ、オブジェクトがそのベクトルに移動され、古い割り当てが解放されます。

すべてのローカル変数と同様に、デストラクタは、実行が宣言されたスコープの最後に到達したときに呼び出されます。したがって、関数が終了する前に、ベクトルデストラクタが呼び出され、その後でのみスタックが縮小され、制御が呼び出し元に戻ります。

于 2012-04-28T18:54:40.717 に答える
3

vecまた、ベクトル( )はオブジェクト自体であることに注意してください。これはスタック上にあり、このオブジェクトがスコープ外になると(このmain場合は終わりです)、破棄されます。要素のメモリは、このオブジェクトの初期化中に割り当てられ、破棄とともに解放されます。これは、要素のリソース管理がベクトルオブジェクトの寿命に関連付けられているため、RAIIイディオムのすばらしい例です。

于 2012-04-28T18:56:57.577 に答える
0

ヒープ内のベクトルのアドレスをsubに指定したため、ヒープ内に割り当てられます。スペースが残っていない場合は、例外をスローする必要があります。

于 2012-04-28T18:45:45.567 に答える