C++では、デストラクタで何かすることが大好きです。しかし、どのような状況では、デストラクタは呼ばれませんか?以下の例でどのような状況で、C++デストラクタは呼び出されませんか?
例:
TerminateProcess()
のうちスレッドで
exit()
コール- 未処理の例外と終了コンピュータのパワー...
C++では、デストラクタで何かすることが大好きです。しかし、どのような状況では、デストラクタは呼ばれませんか?以下の例でどのような状況で、C++デストラクタは呼び出されませんか?
例:
TerminateProcess()
のうちスレッドで
exit()
コールplacement newでオブジェクトを作成した場合、このオブジェクトのデストラクタは自動的に呼び出されません。
定期的にも新品です。新しいプレースメントについては何も新しいことはありません。 – slaphappy
@kbok:言い換えれば、「ダイナミックオブジェクトには手動でライフタイムが管理されています。 –
これは例外をスローする稀なデストラクタにとって特に危険です。多くのコンテナは、格納されたオブジェクトのデストラクタが例外をスローすると、オブジェクトとメモリをリークします。 –
スローされた例外のために呼び出されている別のデストラクタで例外をスローします。
これは単純に 'std :: terminate'を呼び出します。これはデストラクタを呼び出さないように既に設定されています。 –
@MooingDuck Ah。私はあなたがこの答えを投稿したのと同時にコメントに入れているのを見ます。申し訳ありません。 –
これは、すべてのC++プログラマが知っておくべき一つのケースです:
#include <stdio.h>
class EmbeddedObject {
private:
char *pBytes;
public:
EmbeddedObject() {
pBytes = new char[1000];
}
~EmbeddedObject() {
printf("EmbeddedObject::~EmbeddedObject()\n");
delete [] pBytes;
}
};
class Base {
public:
~Base(){
printf("Base::~Base()\n");
}
};
class Derived : public Base {
private:
EmbeddedObject emb;
public:
~Derived() {
printf("Derived::~Derived()\n");
}
};
int main (int argc, const char * argv[])
{
Derived *pd = new Derived();
// later for some good reason, point to it using Base pointer
Base* pb = pd;
delete pb;
}
~Base()
が呼び出されますが、~Derived()
はしません。つまり、~Derived()
のコードは実行されません。それは何か重要なことをしなければならないかもしれない。また、それはEmbeddedObject
のデストラクタが自動的に呼び出されているはずですが、そうではありません。したがって、EmbeddedObject
は、動的に割り当てられたデータを解放する機会を得ることはありません。これにより、メモリリークが発生します。アップにDerived::~Derived()
、EmbeddedObject::~EmbeddedObject()
、Base::~Base()
読む:
ソリューション、クラスBase
virtual
にデストラクタを作る:上記のプログラムには、この1つの変更を作る
class Base {
public:
virtual ~Base() {
}
};
は、すべてのデストラクタがこのオーデルで呼び出されることを意味します一般的にデストラクタ。この種の問題は、あなたが言及している他のシナリオよりも懸念される可能性が高いです。たとえば、パワーダウンの場合、安全なクリーンアップのためのすべてのベットは通常オフです!
C++では、デストラクタの呼び出しを強制的に実行させることができます。これは良いニュースです。しかし、あなたが書いているプログラムでは、あなたのオブジェクトが漏れてしまい、十分に注意を払わなければ削除されない可能性があります。
この場合、未定義の動作ですが、実際には動作します。しかし、 'Std :: string'を' Derived'に入れれば、実際のメモリリークも発生します。 –
「未定義の動作ですが、実際には動作しますか?」ということを明確にすることはできますか?仮想デストラクタまたは非仮想デストラクタ。 – ScrollerBlaster
非仮想は未定義の振る舞いですが、 'Derived'には些細なデストラクタとメンバーがないので、実際にはうまくいくと思います。 –
デストラクタは、無限ループの範囲外のオブジェクトに対しては呼び出されません。
I ... but ... +1。 –
述べた明白なものからアパートすなわち終了()、信号を殺す、停電など
呼び出されるデストラクタを妨げるようないくつかの非常に一般的なプログラミングエラーがあります。
1)オブジェクトの動的配列は、あなたの代わりに無料()を呼び出す代わりに、オブジェクト上)(削除を呼び出す) object* x = new object[n]
で作成されますが、delete x
代わりdelete[] x;
の
2で解放されます。メモリは通常解放されますが、デストラクタは呼び出されません。
3)仮想デストラクタを宣言する必要があるオブジェクト階層があるとしますが、何らかの理由で仮想デストラクタがありませんでした。サブクラスインスタンスの1つが階層構造内の異なる型にキャストされ、削除された場合、すべてのデストラクタを呼び出すことはできません。
核攻撃... – Mysticial
例外が処理されなくなったときでもデストラクタは呼び出されます。あなたのコンピュータが壊滅的に失敗する(プログラムの観点から)すべての理由を列挙しようとすると、役に立たず有用な情報ではなくなり、依然としてデストラクタを使い続けて、とにかく呼び出されると仮定し続けるべきです。 – meagar
antediluvian Flood ... –