Menu
CoddyTech

デストラクタ徹底解説

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 を作成します。コード 1 と 2 のアクティビティを2つ記録し、"Stack session activities: <count>" を出力します。ブロックが終了すると、デストラクタが自動的に実行されます。
    • ブロックの後に、"Stack session destroyed" を出力します
    • ユーザー名 "Guest"、セッションID 202、ログサイズ 3 を指定し、new を使用してヒープに割り当てられた Session を作成します。コード 5 のアクティビティを1つ記録し、"Heap session activities: <count>" を出力してから、明示的に delete します。
    • 削除後に、"Heap session destroyed" を出力します

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

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

自分で試してみよう

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

using namespace std;

int main() {
    // 入力を読み取る
    string username;
    int logSize;
    getline(cin, username);
    cin >> logSize;
    
    // TODO: 波括弧 { } でスコープブロックを作成する
    // ブロック内:
    //   - 入力のユーザー名、セッションID 101、入力のログサイズでスタックに割り当てられたSessionを作成する
    //   - コード1と2で2つのアクティビティをログする
    //   - Print "Stack session activities: <count>"
    // ブロックが終了すると、デストラクタが自動的に実行される
    
    // TODO: After the block, print "Stack session destroyed"
    
    // TODO: newを使ってヒープに割り当てられたSessionを作成する
    //   - ユーザー名: "Guest"、セッションID: 202、ログサイズ: 3
    //   - コード5で1つのアクティビティをログする
    //   - Print "Heap session activities: <count>"
    //   - セッションを削除する
    
    // TODO: After deletion, print "Heap session destroyed"
    
    return 0;
}
quiz icon腕試し

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

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

自分で練習してみよう: C++オンラインコンパイラ