私は現在、クラスとコンストラクタ/デストラクタについて学ぼうとしています。2 つが何をするかは理解していますが、デストラクタを使用するための実用的なアプリケーションが思いつかないため、デストラクタで苦労しています。
誰でも説明付きの例を提供できますか?
私は現在、クラスとコンストラクタ/デストラクタについて学ぼうとしています。2 つが何をするかは理解していますが、デストラクタを使用するための実用的なアプリケーションが思いつかないため、デストラクタで苦労しています。
誰でも説明付きの例を提供できますか?
デストラクタは、オブジェクトによって割り当てられたリソースを解放するために使用される特別なメンバー関数です。
最も一般的な例は、クラスのコンストラクターが を使用new
し、デストラクタが を使用delete
してメモリの割り当てを解除する場合です。
class Myclass
{
int *m_ptr;
public:
Myclass():m_ptr(new int)
{
}
~Myclass()
{
delete m_ptr;
}
//ToDo: Follow Rule of Three
//Provide definitions for copy constructor & copy assignment operator as well
};
デストラクタはおそらくc++の最も重要な側面であり、リソースを管理し、ハンドルの割り当て解除、ソケットからの切断、DBなどの特別なクリーンアップを処理するコードを追加できるようにします。BjarneStroustupは、これは素晴らしいことの1つでもあると述べています。デストラクタについて:
ポジティブな驚きもありました。最も壮観なのは、リソース管理とエラー処理(例外を使用)に関連する手法でのデストラクタの普及です。デストラクタが良いアイデアであることは知っていましたが、結局のところ、コンストラクタの効果を元に戻す必要がありますが、C++をうまく利用するためにデストラクタがどれほど中心的であるかはわかりませんでした。
元の記事: http: //msdn.microsoft.com/en-us/magazine/cc500572.aspx
また、イディオムRAII(Resource Acquisition Is Initialization)にも不可欠であり、この記事でBjarneによって説明されています: http ://www.artima.com/intv/modern3.html
デストラクタに関するこのC++のFAQを読むと、さらに役立つはずです。
Alsのコードサンプルは良い例だと思います。また別の例であるウィキペディアの記事でコードサンプルを見ることができます。オブジェクトがスコープ外になったとき、または呼び出されたときにデストラクタが呼び出されるという事実delete
は非常に便利です。私が使用しているのは、特定の関数呼び出しにかかる時間を計測するためのタイマーオブジェクトクラスです。
class myTimer
{
mytimer():startTime( TimeNow() )
{}
~myTimer()
{
printf("time taken :%I64d", TimeNow() - startTime);
}
private:
__int64 startTime;
};
だから私のコードではこのようなことをします
myClass::myFunction()
{
myTimer timer; // initiliases time to Now.
someOtherFunc();
} // mytimer object is now out of scope and the destructor is called and prints the time it took
たとえば、ファイル操作用のクラスがあり、ifstream
このファイルが自動的に閉じられてクラスのインスタンスが消えるようにしたいとします。デストラクタでファイル ハンドルを閉じます。
これらは、動的に割り当てられたオブジェクトの構成がある場合に最も強力になります
linkedList
リストへのポインタを保持する構造を作成しているとしlinkedListNodes
ましょう。最初の要素へのポインタを保持し、最後の要素を1つまたは2つに応じて保持します。
デストラクタでは、リスト内のすべての要素、つまりリスト自体を削除します。
デストラクタをコーディングしないと、リストがスコープ外になるか、リストにdeleteが呼び出されると、それらの要素に割り当てられていたメモリが失われ、システムで再利用できなくなります(特にメモリリークと呼ばれます)。
ここで@Alsの答えを拡張します。たとえば、クラスがあります。
class A {
B* ptrB; // B is another class / struct / internal type
A() { ptrB = new B(); }
}
int main() {
A* ptrA = new A();
// Do something with A
delete ptrA; // This does not free ptrA->ptrB
}
この問題に対処するには、次のように A でデストラクタを宣言します。
~A() { delete ptrB; } // This is called every time delete is called on
// an object of A
コンストラクタとデストラクタは、RAII (Resource Allocation Is Initialization) イディオムの非常に重要な要素です。リソース (ファイル、メモリ、ソケット、その他のクラス オブジェクト) の取得をオブジェクトの有効期間にリンクすることは、非常に強力なツールです。通常の実行または例外によってオブジェクトがスコープ外になった場合、オブジェクト デストラクタを呼び出すと、多くの追加のファイナライズ手順でオブジェクトを使用してコードに負担をかけることなく、クラスがリソースを適切にクリーンアップできます。