Menu
Coddy logo textTech

デストラクタ詳解

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

デストラクタは、オブジェクトが破棄されるときに自動的に実行される特別なメンバ関数です。その主な役割は、動的に割り当てられたメモリ、ファイルハンドル、ネットワーク接続など、オブジェクトがその生存期間中に取得したリソースを解放することです。

デストラクタはクラスと同じ名前を持ち、先頭にチルダ ~ が付加されます。引数は取らず、戻り値の型もありません:

class FileHandler {
    std::string filename;
    int* buffer;
public:
    FileHandler(std::string name, size_t size) 
        : filename(name), buffer(new int[size]) {
        std::cout << "Opening " << filename << "\n";
    }
    
    ~FileHandler() {
        delete[] buffer;
        std::cout << "Closing " << filename << "\n";
    }
};

デストラクタは、次のような状況で自動的に呼び出されます:

  • スタックオブジェクトがスコープ外になる
  • ヒープに割り当てられたオブジェクトに対して delete が呼び出される
  • 一時オブジェクトの寿命が終了する
void example() {
    FileHandler f1("data.txt", 100);    // コンストラクタが呼び出されます
    
    FileHandler* f2 = new FileHandler("log.txt", 50);
    delete f2;                           // f2 のデストラクタが呼び出されます
    
}   // f1 のデストラクタが呼び出されます(スコープ外になるため)

コンストラクタとは異なり、クラスはデストラクタを1つしか持つことができません。オーバーロードすることはできません。

デストラクタを定義しない場合、コンパイラは特別な処理を行わないデフォルトのデストラクタを生成します。これは単に各メンバを破棄するだけのものです。リソースを管理するクラスでは、メモリリークを防ぐために独自のデストラクタを記述する必要があります。

challenge icon

チャレンジ

簡単

アクティブなユーザーセッションを追跡し、オブジェクトが破棄される際(スコープ外に出るか、明示的に削除されるかに関わらず)にデストラクタがどのようにリソースを自動的にクリーンアップするかを実演するセッションマネージャーを構築しましょう。

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

  • Session.h: 動的に割り当てられたデータを持つアクティブなユーザーセッションを表す Session クラスを定義します。クラスには以下のものを含める必要があります:
    • プライベートメンバ:username (string)、sessionId (int)、ユーザーのアクションを追跡する activityLog という名前の整数配列へのポインタ、および配列サイズのための logSize
    • ユーザー名、セッションID、ログサイズを受け取るコンストラクタ。ヒープ上にアクティビティログ配列を割り当て、すべての要素を 0 に初期化し、"Session <sessionId> started for <username>" と出力する必要があります
    • 割り当てられたメモリを解放し、"Session <sessionId> ended for <username>" と出力するデストラクタ
    • アクティビティコードを次に利用可能なスロットに格納する logActivity(int activityCode) メソッド(内部で現在の位置を追跡します)
    • これまでに記録されたアクティビティの数を返す getActivityCount() メソッド
    • ユーザー名を返す getUsername() メソッド
  • main.cpp: さまざまなシナリオにおけるデストラクタの動作を実演します。入力からユーザー名とログサイズを読み取り(それぞれ別の行)、以下の処理を行います:
    • 波括弧 { } を使用してスコープブロックを作成し、その中で入力されたユーザー名、セッションID 101、および入力されたログサイズを使用して、スタックに割り当てられた Session を作成します。コード 12 の2つのアクティビティをログに記録し、"Stack session activities: <count>" と出力します。ブロックが終了すると、デストラクタが自動的に実行されるはずです。
    • ブロックの後に、"Stack session destroyed" と出力します。
    • new を使用して、ユーザー名 "Guest"、セッションID 202、ログサイズ 3 でヒープに割り当てられた Session を作成します。コード 5 のアクティビティを1つログに記録し、"Heap session activities: <count>" と出力してから、明示的に delete します。
    • 削除後に、"Heap session destroyed" と出力します。

このチャレンジでは、デストラクタが呼び出される2つの主な方法を示しています。スタックオブジェクトがスコープを抜けるときに自動的に呼び出される方法と、ヒープオブジェクトを削除するときに手動で呼び出される方法です。どちらの経路でも、メモリリークを防ぐために動的に割り当てられたアクティビティログを適切に解放する必要があります。

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

チートシート

デストラクタは、オブジェクトが破棄されるときに自動的に実行される特別なメンバ関数です。動的に割り当てられたメモリ、ファイルハンドル、ネットワーク接続などのリソースを解放します。

デストラクタはクラスと同じ名前を持ち、先頭にチルダ ~ が付きます。引数は取らず、戻り値の型もありません:

class FileHandler {
    std::string filename;
    int* buffer;
public:
    FileHandler(std::string name, size_t size) 
        : filename(name), buffer(new int[size]) {
        std::cout << "Opening " << filename << "\n";
    }
    
    ~FileHandler() {
        delete[] buffer;
        std::cout << "Closing " << filename << "\n";
    }
};

デストラクタは、次の場合に自動的に呼び出されます:

  • スタックオブジェクトがスコープ外になったとき
  • ヒープに割り当てられたオブジェクトに対して delete が呼び出されたとき
  • 一時オブジェクトの寿命が終了したとき
void example() {
    FileHandler f1("data.txt", 100);    // コンストラクタが呼び出される
    
    FileHandler* f2 = new FileHandler("log.txt", 50);
    delete f2;                           // f2 のデストラクタが呼び出される
    
}   // f1 のデストラクタが呼び出される(スコープ外になるため)

クラスは**1つのデストラクタ**しか持つことができません(オーバーロードは不可)。デストラクタを定義しない場合、コンパイラがデフォルトのデストラクタを生成します。リソースを管理するクラスでは、メモリリークを防ぐために独自のデストラクタを記述する必要があります。

自分で試してみよう

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

using namespace std;

int main() {
    // 入力を読み込む
    string username;
    int logSize;
    getline(cin, username);
    cin >> logSize;
    
    // TODO: 波括弧 { } を使用してスコープブロックを作成する
    // ブロック内:
    //   - 入力された username、セッションID 101、および入力された logSize を使用して、スタック割り当ての Session を作成する
    //   - コード 1 と 2 の2つのアクティビティをログに記録する
    //   - "Stack session activities: <count>" を出力する
    // ブロックが終了すると、デストラクタが自動的に実行される
    
    // TODO: ブロックの後で、"Stack session destroyed" を出力する
    
    // TODO: new を使用してヒープ割り当ての Session を作成する
    //   - Username: "Guest"、セッションID: 202、log size: 3
    //   - コード 5 のアクティビティを1つログに記録する
    //   - "Heap session activities: <count>" を出力する
    //   - セッションを delete する
    
    // TODO: 削除後、"Heap session destroyed" を出力する
    
    return 0;
}
quiz icon腕試し

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

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