web-dev-qa-db-ja.com

std :: vectorはどこにメモリを割り当てますか?

次のコードスニペットを検討してください。

#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はヒープ上の要素にメモリを割り当てますか?しかし、そのヒープメモリをどのように解放するのでしょうか。スタック上のローカルベクトルの場合、削除されることをベクトルに通知せずに、ベクトルを含む関数のスタックフレームが最後に削除されますか?

28
YoFrankie

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

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

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

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

35
Doug T.

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

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

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

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

17
Matthieu M.

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

2
LihO

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

0
Stefan