Menu
Coddy logo textTech

スタック vs ヒープメモリ

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 12/104。

C++プログラムは、主に2つのメモリ領域を使用します:スタックヒープです。オブジェクトがどこに配置されるかを理解することは、効率的でバグのないコードを書くために不可欠です。

スタックは、高速で自動的なメモリです。関数内で宣言された変数はここに配置され、スコープ外になると自動的に破棄されます。

void example() {
    int x = 10;           // スタック割り当て
    Player player;        // スタック割り当て - 自動的に破棄されます
}   // x と player はここで破棄されます

ヒープは、手動で管理する、より大きく低速なメモリです。ヒープ上のオブジェクトは、明示的に削除するまで存続します。

void example() {
    Player* player = new Player();  // ヒープ割り当て
    // player は削除されるまで存在します
    delete player;                   // 手動でのクリーンアップが必要
}

主な違い:

スタックヒープ
高速な割り当て低速な割り当て
制限されたサイズ大容量
自動クリーンアップ手動クリーンアップが必要
固定サイズのオブジェクト動적サイズのオブジェクト

小さく、短命なオブジェクトにはスタック割り当てを使用します。オブジェクトがスコープを超えて生存する必要がある場合や、サイズが実行時に決定される場合には、ヒープ割り当てを使用します。

ヒープメモリの削除を忘れることは、C++プログラムにおける一般的なバグの原因であるメモリリークを引き起こします。

challenge icon

チャレンジ

簡単

オブジェクトがどのように作成され、破棄されるかを追跡するシンプルな Counter クラスを構築することで、スタックメモリとヒープメモリの違いを探ってみましょう。

コードを整理するために、2つのファイルを作成します。

  • Counter.h: プライベートな name 属性(string)を持つ Counter クラスを定義します。名前を受け取り "Creating: <name>" と出力するコンストラクタと、"Destroying: <name>" と出力するデストラクタを含めます。カウンターの名前を返す getName() メソッドを追加してください。
  • main.cpp: スタック割り当てとヒープ割り当ての両方を実演します。入力から名前を読み取り、以下の処理を行います:
    • その名前を使用して、スタックに割り当てられた Counter を作成する
    • "HeapCounter" という名前で、ヒープに割り当てられた Counter を作成する
    • 両方のカウンター名を "Stack: <name>" および "Heap: <name>" の形式で出力する
    • メモリリークを防ぐために、ヒープに割り当てられたカウンターを削除(delete)する

各オブジェクトを作成および削除するタイミングによって、コンストラクタとデストラクタのメッセージが異なる順序で表示されることを確認してください。スタックオブジェクトは main() が終了すると自動的に破棄されますが、ヒープオブジェクトは明示的に削除する必要があります。

main.cpp で #include "Counter.h" を使用してヘッダーファイルをインクルードしてください。

チートシート

C++プログラムは、主に2つのメモリ領域を使用します。スタックヒープです。

スタックは高速で自動的なメモリです。関数内で宣言された変数はここに配置され、スコープ外に出ると自動的に破棄されます。

void example() {
    int x = 10;           // スタック割り当て
    Player player;        // スタック割り当て - 自動的に破棄される
}   // xとplayerはここで破棄される

ヒープはより大容量ですが、手動で管理する低速なメモリです。ヒープ上のオブジェクトは、明示的に削除するまで存続します。

void example() {
    Player* player = new Player();  // ヒープ割り当て
    // playerは削除されるまで存在する
    delete player;                   // 手動でのクリーンアップが必要
}

主な違い:

スタックヒープ
高速な割り当て低速な割り当て
サイズ制限あり大容量
自動クリーンアップ手動クリーンアップが必要
固定サイズのオブジェクト動的サイズのオブジェクト

小さく短命なオブジェクトにはスタック割り当てを使用します。オブジェクトがスコープを超えて存続する必要がある場合や、実行時にサイズが決定される場合にはヒープ割り当てを使用します。ヒープメモリの削除を忘れると、メモリリークが発生します。

自分で試してみよう

#include <iostream>
#include <string>
#include "Counter.h"

using namespace std;

int main() {
    // 入力から名前を読み取る
    string inputName;
    cin >> inputName;

    // TODO: inputName を使用してスタック割り当ての Counter を作成する

    // TODO: 名前が "HeapCounter" のヒープ割り当ての Counter を作成する

    // TODO: スタックカウンターの名前を "Stack: <name>" の形式で出力する

    // TODO: ヒープカウンターの名前を "Heap: <name>" の形式で出力する

    // TODO: メモリリークを防ぐためにヒープ割り当てのカウンターを削除する

    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン