モダンC++とCでの代替手法

C++のRAIIとリソースの自動解放

このレッスンでは、Cでファイルを安全に閉じる方法と、リソースが自動で解放されるC++のRAIIを比べます。

はじめに

RAII(Resource Acquisition Is Initialization)は、ファイル、メモリ領域、接続などのリソースの寿命を、オブジェクトの寿命に結び付ける手法です。オブジェクトが破棄されると、例外が起きた場合も含めて、ブロックから抜けるどの道筋でもリソースが自動で解放されます。

大切なポイント

  • C++の抽象化を学ぶ前に、Cでのやり方を理解しましょう。
  • RAIIと値のセマンティクス(value semantics)で、リソースの持ち主を表しましょう。
  • マクロや型変換より、C++の型安全な道具を優先しましょう。

CとC++のコード例

C
実行 →
main.c
#include <stdio.h>

int main(void) {
    int result = 1;
    FILE *file = fopen("scores.txt", "w");
    if (!file) goto cleanup;
    if (fputs("Ada 95\n", file) < 0) goto cleanup;
    result = 0;

cleanup:
    if (file) fclose(file);
    puts(result ? "failed" : "saved");
    return result;
}
実行結果
saved
C++
実行 →
main.cpp
#include <fstream>
#include <iostream>

int main() {
    std::ofstream file("scores.txt");
    if (!file) return 1;
    file << "Ada 95\n";
    std::cout << "saved\n";
}
実行結果
saved

CとC++の比較

Cでは、ラベルcleanupとgotoを使って、成功でもエラーでもすべての道筋がファイルを閉じるfcloseを通るようにしています。C++では、変数fileがスコープを抜けるときにstd::ofstreamがデストラクター(destructor)でファイルを自動で閉じます。これでリソース管理がすっきりし、解放し忘れる危険も減ります。

C

Cは名前付けの習慣、コールバック、マクロ、文脈を持つstructを使います。

C++

C++はスコープがはっきりした型安全な抽象化を用意しており、実行時のコストはふつうかかりません。

発展問題

両方のバージョンを実行し、コードを書き換えて、それぞれの言語がもたらす安全性の違いを観察しましょう。

  • まずCで仕組みを書き、その後で対応するC++の機能を使いましょう。
  • 手作業のリソース解放をRAIIに置き換えましょう。
  • その機能がメモリの確保や仮想関数の呼び出しを生むかどうかを確認しましょう。

チャレンジで練習する

このレッスンの内容を使って実際の問題を解きましょう。各チャレンジはブラウザで動き、すぐにテストされ、AI のレビューも受けられます。

すべてのチャレンジ