Menu
Coddy logo textTech

デストラクタ徹底解説

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

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

The destructor は class と同じ名前を持ち、チルダ ~ を前置します。パラメーターを取らず、戻り値の型もありません。

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";
    }
};

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

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

constructorとは異なり、classにはdestructorを1つだけ持たせることができます。destructorをオーバーロードすることはできません。

define しない場合、コンパイラーは特別な処理を何もしない default destructor を生成します。つまり、各 member を単純に破棄するだけです。リソースを管理する class では、メモリリークを防ぐために自分で destructor を記述する必要があります。

challenge icon

チャレンジ

簡単

アクティブなユーザーセッションを追跡し、オブジェクトがスコープ外に出た場合や明示的に削除された場合など、オブジェクトが破棄されたときにデストラクタがリソースを自動的に Clean する仕組みを示すセッションマネージャーを作成しましょう。

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

  • Session.h:動的に割り当てられた data を持つアクティブなユーザーセッションを表す Session class を define します。class には次の要素を含めます。
    • private メンバー:username(string)、sessionId(int)、ユーザーの操作を追跡する activityLog という整数 array へのポインター、および array のサイズを示す logSize
    • username、session ID、log size を受け取る constructor。activity log array を heap 上に allocate し、すべての elements を 0 に初期化して、"Session <sessionId> started for <username>" を表示します
    • allocate されたメモリを解放し、"Session <sessionId> ended for <username>" を表示する destructor
    • activity code を次に available なスロットに格納する logActivity(int activityCode) method(current position は内部で追跡します)
    • 記録された activities の数を返す getActivityCount() method
    • username を返す getUsername() method
  • main.cpp:さまざまな状況での destructor の動作を示します。入力から username と log size を読み込み(それぞれ別の行に入力)、次の処理を行います。
    • curly braces { } を使用して scope block を作成し、その中で、入力された username、session ID 101、入力された log size を使って stack に allocate された Session を作成します。codes 12 の2つの activities を記録し、"Stack session activities: <count>" を表示します。block が ends すると、destructor が automatically 実行されます。
    • block の After に、"Stack session destroyed" を表示します
    • username "Guest"、session ID 202、log size 3 を指定し、new を使用して heap に allocate された Session を作成します。code 5 の activity を1つ記録し、"Heap session activities: <count>" を表示してから、明示的に delete します。
    • deletion の After に、"Heap session destroyed" を表示します

この challenge では、destructor が呼び出される2つの主な方法を示します。stack object が scope を離れたときに automatically 呼び出される方法と、heap object を delete したときに手動で呼び出される方法です。どちらの経路でも、メモリリークを防ぐために、Dynamically allocate された activity log が適切に解放される必要があります。

#include "Session.h" を使用して、header file を main.cpp に include してください。

自分で試してみよう

#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++オンラインコンパイラ