はじめに
C++のコンストラクタが、オブジェクトが「生まれる」瞬間に自動で呼ばれる初期化処理であるのに対し、「デストラクタ (Destructor)」は、オブジェクトがメモリ上から「消滅する」直前に自動で呼び出される、後片付けのための特別なメンバ関数です。
デストラクタの主な役割は、オブジェクトが使用していたメモリやファイルハンドルなどのリソースを、プログラムに安全に返却することです。これにより、メモリリークなどの問題を未然に防ぐことができます。
この記事では、デストラクタの基本的な定義方法と、どのようなタイミングで呼び出されるのかを、分かりやすく解説します。
デストラクタの定義ルール
デストラクタには、コンストラクタと同様に、厳密なルールがあります。
- 関数名は、クラス名の前にチルダ (
~
) を付けたものでなければならない。 - 戻り値の型(
void
も含む)を記述してはならない。 - 引数を持つことはできない。
- 一つのクラスに複数定義(オーバーロード)することはできない。
デストラクタを使ったサンプルコード
このコードは、MyObject
クラスにコンストラクタとデストラクタを定義し、オブジェクトが生成されるタイミングと、スコープを抜けて破棄されるタイミングを追跡します。
完成コード
#include <iostream>
#include <string>
using namespace std;
class MyObject {
public:
string name;
// コンストラクタ
MyObject(string n) {
name = n;
cout << "コンストラクタ: オブジェクト「" << name << "」が生成されました。" << endl;
}
// デストラクタ
~MyObject() {
cout << "デストラクタ: オブジェクト「" << name << "」が破棄されます。" << endl;
}
};
// testFunctionのスコープ
void testFunction() {
cout << "--- testFunctionを開始 ---" << endl;
MyObject obj_in_func("関数内のオブジェクト");
cout << "--- testFunctionを終了 ---" << endl;
// ここで obj_in_func のスコープが切れるため、デストラクタが呼ばれる
}
// main関数のスコープ
int main() {
cout << "--- main関数を開始 ---" << endl;
testFunction(); // 関数を呼び出す
MyObject obj_in_main("main内のオブジェクト");
cout << "--- main関数を終了 ---" << endl;
return 0;
// ここで obj_in_main のスコープが切れるため、デストラクタが呼ばれる
}
実行結果
--- main関数を開始 ---
--- testFunctionを開始 ---
コンストラクタ: オブジェクト「関数内のオブジェクト」が生成されました。
--- testFunctionを終了 ---
デストラクタ: オブジェクト「関数内のオブジェクト」が破棄されます。
コンストラクタ: オブジェクト「main内のオブジェクト」が生成されました。
--- main関数を終了 ---
デストラクタ: オブジェクト「main内のオブジェクト」が破棄されます。
コードの解説
~MyObject()
これがデストラクタの定義です。クラス名 MyObject
の前にチルダ ~
が付いています。引数も戻り値もありません。
デストラクタが呼び出されるタイミング
デストラクタは、オブジェクトの「スコープ」が終了するタイミングで自動的に呼び出されます。スコープとは、その変数が有効な範囲のことです。
obj_in_func
:testFunction
の{}
の中で宣言されているため、testFunction
が終了する}
の時点でスコープを抜け、デストラクタが呼び出されます。obj_in_main
:main
関数の中で宣言されているため、main
関数が終了する}
の時点でスコープを抜け、デストラクタが呼び出されます。
実行結果の出力順を見ると、オブジェクトが生成されたときにはコンストラクタが、そのオブジェクトが有効範囲を抜けるときにはデストラクタが、それぞれ対応して呼び出されていることが明確に分かります。
new
と delete
new
演算子を使って動的にメモリを確保したオブジェクトの場合は、スコープが切れても自動では破棄されません。delete
演算子を明示的に呼び出したタイミングで、デストラクタが実行されます。
まとめ
今回は、C++のデストラクタの基本的な役割と使い方について解説しました。
- デストラクタは、オブジェクトが破棄される直前に自動で呼び出される後片付け用の関数。
- 関数名は
~クラス名
で、引数も戻り値もない。 - 主な目的は、オブジェクトが使用したメモリなどのリソースを解放すること。
単純なクラスではデストラクタを明示的に書く必要はあまりありませんが、new
で確保したメモリを解放するなど、後片付けが必要なクラスを設計する際には、デストラクタの役割が非常に重要になります。