RAII: リソース管理の原則

コンストラクタで獲得、デストラクタで解放。リークを防ぐ。

RAII
Resource Acquisition Is Initialization.
コンストラクタ
リソースを獲得。
デストラクタ
リソースを解放。

RAII

レンタカー (Rental Car)

RAIIはレンタカーです。車を借りる(コンストラクタ)と鍵をもらいます。契約終了時(デストラクタ/スコープ離脱)には、必ず鍵を返さなければなりません。C++では、この「返却」が自動で行われるため、返し忘れ(リーク)が起きません。

多くの言語ではGC(ガベージコレクション)がメモリを管理しますが、ファイルやネットワーク接続などのリソースは管理してくれません(`close()`や`dispose()`が必要)。RAIIは、メモリだけでなく「あらゆるリソース」の寿命をスコープと連動させて管理する、C++最強の機能です。

RAII Class
class FileHandle {
FILE* file_;
public:
// コンストラクタでリソース獲得
FileHandle(const char* path) : file_(fopen(path, "r")) {
if (!file_) throw std::runtime_error("Cannot open");
}
// デストラクタでリソース解放
~FileHandle() {
if (file_) fclose(file_);
}
// コピー禁止
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// ムーブは許可
FileHandle(FileHandle&& other) noexcept : file_(other.file_) {
other.file_ = nullptr;
}
};
効果
// スコープ終了時に自動解放\nFile closed automatically
Bad
// ❌ Bad: 手動リソース管理
FILE* f = fopen("data.txt", "r");
// ... 処理 ...
fclose(f); // 例外時に実行されない
Good
// ✅ Good: RAII でリソース管理
{
FileHandle f("data.txt");
// ... 処理 ...
} // 自動で fclose

標準ライブラリの RAII

Smart Pointers, lock_guard
// 標準ライブラリの RAII クラス
std::unique_ptr<int> // 動的メモリ
std::shared_ptr<int> // 共有所有権
std::lock_guard // mutex ロック
std::fstream // ファイル
std::thread // スレッド
// ロックの RAII
std::mutex m;
{
std::lock_guard<std::mutex> lock(m);
// クリティカルセクション
} // 自動アンロック
// C++17: scoped_lock(複数mutex対応)
std::scoped_lock lock(m1, m2);
Tip: 新規リソースは smart_ptr や標準RAII を使う。自作は最終手段。

合格ライン

RAII の原則を説明できる
lock_guard を使える

参考リンク

演習課題

課題1: RAII ファイルハンドル
ファイルのオープン/クローズを RAII でラップするクラスを作成してください。
課題2: lock_guard
lock_guard を使ってミューテックスを管理してください。

次のステップ