クラスがC++クラスでデストラクタを定義する必要があるのはいつですか?なぜですか?
C ++でこれを学び始めたばかりで、明確にする必要があります。
動的に割り当てられたメモリを解放するなど、クラスが特別なクリーンアップを行う必要がある場合にのみ、デストラクタを定義する必要があります。
動的にメモリを割り当てた場合は、デストラクタを定義する必要があります。経験則として、コンストラクターのいずれかで new を使用する場合、おそらくデストラクタが必要です。自動ストレージでも静的ストレージでもないものは、動的に割り当てられたと見なされます
クリーンアップのカテゴリに該当するものはすべて、たとえばネットワーク接続を閉じるなど、デストラクタに入れるのが適切です
他にも理由があるかもしれませんが、私が考えている最初の理由は、クラス属性の一部を明示的に解放する必要があるかもしれないということです。
クラスに 2 つの int 属性があるだけの場合、それらは を呼び出すときにオブジェクトとともに自動的に削除されますdelete myObject
。ただし、動的に割り当てられた属性が含まれている場合、それらはオブジェクトとともに解放されないため、デストラクタで明示的に削除する必要があります。
デストラクタのデフォルトの動作が希望どおりでない場合にのみ、デストラクタを定義する必要があります。
オブジェクトが破棄されると、カスタム デストラクタを定義するかどうかに関係なく、デストラクタは次のことを行います。
これは、実際にやりたいことのほとんどを処理します。コンストラクターでメモリが割り当てられたときに、カスタム デストラクタを定義するのが一般的でした。
struct A {
B *b_ptr;
A() : b_ptr(new B) { }
~A() { delete b_ptr; }
};
ただし、標準コンテナーとスマート ポインターを使用している場合、カスタム デストラクタが必要になるケースは比較的少なくなります。たとえば、このようなクラスがある場合
struct A {
std::unique_ptr<B> b_ptr;
A() : b_ptr(new B) { }
};
std::unique_ptr が割り当てられたメモリを解放するため、独自のデストラクタを定義する必要はありません。同様に、ここでデストラクタを定義する必要はありません
struct B {
ifstream input_stream;
B(const std::string &path) : input_stream(path) { }
};
はinput_stream
、input_stream メンバーが破棄されると自動的に閉じられるためです。
場合によっては、何か特別なことをしなければならない場合もあります。リソースを取得または解放するには、特別な呼び出しが必要です。その場合、デストラクタが必要です。
struct C {
ResourceHandle resource_handle;
C() : resource_handle(resouce_manager.acquireResource()) { }
~C() { resource_manager.releaseResource(resource_handle); }
};
ただし、多くのクラスで重複する必要がないように、この種の動作をできる限りローカライズする必要があります。たとえば、次のようなクラスを作成したい場合があります。
struct ResourceHolder {
ResourceHandle resource_handle;
ResourceHolder() : resource_handle(acquireResource()) { }
~ResourceHolder() { releaseResource(resource_handle); }
};
これらのリソースのいずれかを必要とする各クラス内で ResourceHolder を使用するだけで、取得と解放のロジックを再度繰り返す必要がなくなりました。
デストラクタは、たとえばコンストラクタで割り当てられたメモリを解放するためだけに使用されるわけではありません。
デストラクタを使用して、 RAII スタイルの機能を実現できます。
これを利用する型の例:
std::fstream
開いているファイルを閉じます
std::lock_guard
ミューテックスのロックを解除します
std::shared_ptr
参照カウンターをデクリメントするか、カウンターが 0 の場合はメモリを解放します。
デストラクタを定義する必要がある 2 つのインスタンスがあります。