この動作は C++ 標準では保証されていません。スタックやヒープについても言及されていません。
ただし、通常、関数を呼び出すと、その関数のすべての自動変数 (および戻り値などの他のオブジェクト) を格納するのに十分な大きさのスタックにスタック フレームがプッシュされます。したがって、関数を考えるとfoo
:
void foo() {
int x;
std::string str;
}
この関数が呼び出されると、スタックの一番上が押し上げられ、int
と のための十分なスペースが確保されstd::string
ます。これらの型のサイズは実装で定義されており、標準によっていくつかの制限が課されていますがsizeof(int)
、sizeof(std::string)
バイトと考えることができます。
関数に などの配列がある場合、関数int a[10]
のスタック フレームには 10int
秒または10*sizeof(int)
バイトに十分なスペースが含まれます。このフレーム サイズは実行可能ファイルに組み込まれます。関数が呼び出されると、スタックはそのサイズだけ増加します。
などの動的割り当てを行う場合、ヒープ内int* a = new int[10]
に 10int
秒または のスペースを割り当てます。10*sizeof(int)
ただし、スタック フレームをある程度増やしましたsizeof(int*)
。ポインター オブジェクト自体はスタックに格納されますが、int
それが指す s はヒープ上にあります。
std::string
最初の例では、が可変長である場合、スタック フレームのサイズを実行可能ファイルにどのように組み込むことができるか疑問に思うかもしれません。これは、std::string
オブジェクト自体のサイズが固定されているためですsizeof(std::string)
が、内部表現を管理するためにある種の動的割り当てを行う可能性が最も高いためです。この内部表現はヒープ上にあります。