本文へスキップ
BecomeCoder

C++コース · 第16章 メモリ管理とスマートポインタ ― 漏らさない所有権 · レッスン64

new / delete と RAII の考え方

ブラウザで完結

導入

第6章で「スタックとヒープ」を学びました。ヒープに確保したメモリnew)は、自分で delete して返さないと漏れます(メモリリーク)。この「手で管理する危うさ」を、C++ は RAII という考え方で解決します。まずは問題を正しく理解しましょう。

説明

new でヒープにメモリを確保し、delete で返します。配列new[] / delete[] です。これを対で正しく呼ぶのは、実は簡単ではありません。

#include <iostream>
using namespace std;

int main() {
    int* p = new int(42);    // ヒープに確保
    cout << *p << endl;      // 42
    delete p;                // 手で返す(忘れると漏れる)

    int* arr = new int[3]{1, 2, 3};
    cout << arr[2] << endl;  // 3
    delete[] arr;            // 配列は delete[]
    return 0;
}

問題は「途中で return した」「例外が飛んだ」ときに delete が飛ばされ、メモリが漏れることです。人間が全経路で解放を保証するのは困難です。

flowchart TB
  n["new で確保"] --> use["処理"]
  use -->|"正常終了"| d["delete(実行される)"]
  use -->|"途中 return / 例外"| leak["delete が飛ばされる → リーク!"]

そこで RAII(Resource Acquisition Is Initialization) の出番です。「資源をオブジェクトに持たせ、確保はコンストラクタ、解放はデストラクタで行う」。すると第10章で見たとおり、スコープを抜けた瞬間にデストラクタが自動で呼ばれ、return でも例外でも確実に解放されます。この RAII を汎用化した標準部品が、次に学ぶスマートポインタです。

まとめ

new/delete の手動管理は、return や例外で漏れやすく危険です。解決策が RAII――「デストラクタで自動的に資源を返す」設計。現代の C++ では生の new/delete を直接書かず、RAII を実装したスマートポインタを使うのが基本です。

実際に動かしてみよう

下のエディタにC++を書いて「コンパイル & 実行」を押すと、ブラウザ内で本物のC++コンパイラ(clang + libc++)がその場でコンパイルして実行し、出力が表示されます。std::string・vector・クラス・テンプレート・STL などモダンC++がそのまま動きます。本文の例を書き換えて試しながら進めましょう(初回だけコンパイラの読み込みに時間がかかります。以降はキャッシュされます。この回は標準入力(cin)は使わず、値はコードに直接書きます)。

C/C++ — ブラウザ内で本物のコンパイラで実行

ブラウザ内で本物のC/C++コンパイラ(clang + libc++ / WebAssembly)を動かします。構造体・malloc/free・std::string・vector・クラス・テンプレート・STL などがそのまま実行できます(初回のみコンパイラの読み込みに時間がかかります。以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。