デストラクタ


オブジェクトの破棄

オブジェクトの実体は自分自身に関する情報やフィールド領域、メソッドへのポインタなどを含んだ情報の塊です。 当然、すべてのオブジェクトは自身の情報を保持するためのメモリ領域が割り当てられているため、オブジェクトを new 演算子で生成するとメモリが消費されます。 C 言語標準関数で malloc() を使って割り当てた領域を free() で解放しなければならないように、オブジェクトが不要になればオブジェクトを破棄し、メモリを解放しなければならないと考えられます。

幸い、D 言語は完全なガベージコレクタを保有するため、開発者がコードを記述してオブジェクトを解放する必要はありません。 ガベージコレクタは利用可能メモリが少なくなるなど、オブジェクトの解放が必要なタイミングで、使われていないオブジェクトを自動的に解放してくれます。

ガベージコレクタがオブジェクトを解放するとき、ガベージコレクタはそのオブジェクトのデストラクタを呼び出そうと試みます。 デストラクタは、オブジェクトが破棄されるタイミングで呼び出されるコンストラクタと対にあたる特殊なメソッドです。 デストラクタは常に ~this() という名前で、戻り値や引数を持たないメソッドとして宣言しなければなりません。

class クラス名 {
	~this() {
		デストラクタ本体
		...
	}
}

デストラクタは、オブジェクトが破棄される直前に呼び出されるため、この時点ではまだオブジェクトのフィールドの値は有効です。 すべてのインスタンスは不要になった時点で必ずデストラクタが呼び出されます。 デストラクタは通常のメソッドからは呼び出すことができまず、かならず 1 度だけ呼び出されることが保証されています。

import std.stream;

class Point { 
	int x , y;
	this(int x , int y) {
		this.x = x;
		this.y = y;
	}
	~this() {
		stdout.printf("Delete Point Object %d, %d\n" , x , y);
	}
}


int main() {
	Point point1 = new Point(100 , 70);
	Point point2 = new Point(50 , 500);
	return 0;
}

このプログラムは、main() メソッドで生成した Point オブジェクトが、プログラム終了時に破棄されることを確認することができます。 Point クラスは明示的に ~this() デストラクタが宣言されているため、ガベージコレクタはオブジェクトを破棄する直前にデストラクタを呼び出します。 デストラクタでは、破棄されるオブジェクトのフィールド値を表示しているため、個々のオブジェクトが正しく管理され、自動的には帰されていることを確認できるでしょう。


delete 式

ガベージコレクタは、オブジェクトの解放を忘れてしまうメモリリークの危険性を回避でき、同時にデバッグの時間を短縮できる生産性を持っています。 しかし、ビットマップイメージや音声データ、マルチメディアデータの制御など、大きなデータを扱うプログラムにとっては、オブジェクトの破棄が後回しになるということが逆に負担になる可能性があります。 このような巨大なデータは、不要になった時点で解放した方が高速に動作したり、システムに与える負荷を少なくすることができるかもしれません。

オブジェクトの解放を手動で行いたい場合、オブジェクトが不要になった時点で delete 式を使うことで明示的にメモリを解放することができます。

delete 式文

delete 式は指定したオブジェクト型の式文が返したインスタンスを確実に破棄します。 特定のタイミングで確実に破棄したいオブジェクトは delete 式を使ってメモリから解放することができるのです。

import std.stream;

class Point { 
	int x , y;
	this(int x , int y) {
		this.x = x;
		this.y = y;
	}
	~this() {
		stdout.printf("Delete Point Object %d, %d\n" , x , y);
	}
}


int main() {
	Point point = new Point(100 , 70);

	stdout.printf("Before\n");
	delete point;
	stdout.printf("After\n");
	return 0;
}

このプログラムは main() メソッドの途中で、生成した Point オブジェクトを delete 式によって明示的に解放しています。 デストラクタが呼び出されるタイミングを見れば、delete に与えられたオブジェクトがメモリから破棄されていることを確認することができます。



前のページへ戻る次のページへ