では、スタックの変数を解放して、ヒープのように新しい変数用のスペースを空けないのはなぜでしょうか?
「スタックアロケータ」が知っているすべての情報はESP
、スタックの一番下へのポインタです。
N: used
N-1: used
N-2: used
N-3: used <- **ESP**
N-4: free
N-5: free
N-6: free
...
これにより、「スタック割り当て」が非常に効率的になります。割り当てESP
のサイズだけ減少するだけでなく、ローカリティ/キャッシュに適しています。
さまざまなサイズの任意の割り当て解除を許可すると、「スタック」が「ヒープ」になり、関連する追加のオーバーヘッドがすべて発生しESP
ますが、どのスペースが割り当て解除され、どのスペースが割り当て解除されていないかを覚えておく必要があるため、十分ではありません。
N: used
N-1: free
N-2: free
N-3: used
N-4: free
N-5: used
N-6: free
...
明らかに -ESP
では十分ではありません。また、断片化の問題にも対処する必要があります。
コンパイラがスタック上の変数を解放していることがわかりますが、それは変数のスコープの最後にあります。スコープの最後でヒープ上の変数も解放しませんか? そうでない場合、なぜですか?
理由の 1 つは、常にそれを望んでいるとは限らないことです。割り当てられたデータを関数の呼び出し元に返したい場合があります。そのデータは、作成されたスコープより長く存続する必要があります。
そうは言っても、「ヒープ」に割り当てられたデータのスコープベースの有効期間管理が本当に必要な場合 (そしてほとんどの場合、実際にはスコープベースです)、C++ ではそのようなデータの周りにラッパーを使用するのが一般的です。例の1つは次のstd::vector
とおりです。
{
std::vector<int> x(1024); // internally allocates array of 1024 ints on heap
// use x
// ...
} // at the end of the scope destructor of x is called automatically,
// which does deallocation