VIDTAKER.COM

Q&A

C + +は:ウィル'空'のデストラクタと同じことを行う生成されたデストラクタとして?


私たちは)(おもちゃがあるとC + +のクラス次のような:

class Foo {
    public:
        Foo();
    private:
        int t;
};

ないデストラクタが定義されて以来、C + +のコンパイラは、いずれかを自動的にFooクラス用に作成してください。デストラクタは(つまり、我々が合理的にコンパイラが与えてくれるのデストラクタに頼ること)は、空のデストラクタを、すなわち定義するすべての動的に割り当てられたメモリをクリーンアップする必要がない場合。

Foo::~Foo() { }

コンパイラによって生成さと同じものですか?

そこが存在するか違いがあるか? 、1つの方法他の優先されていない場合は?

編集には :よくコンストラクタとしては答えを同じか?



6 Replies

1)

それは)本質的に同じことを(何も行います。しかし、それはまるであなたがそれを書いていないと同じではない。作業ベースクラスのデストラクタが必要になりますデストラクタを書くため。基本クラスのデストラクタは、プライベートまたは存在する場合は、お使いのプログラムが故障している起動することができない他の理由である場合。この検討

struct A { private: ~A(); };
struct B : A { };

これは[OK]を、としてあなたのB型のオブジェクト(つまりを破壊する必要はありません限り、暗黙的にA型のです) - のような場合は削除を動的に作成されたオブジェクト上で呼び出すことが場合、またはそれのオブジェクトを作成しない1位。その場合は、コンパイラは、適切な診断が表示されます。今、あなたが提供する場合、1つの明示的

struct A { private: ~A(); };
struct B : A { ~B() { /* ... */ } };

その1つは、暗黙的に基底クラスのデストラクタを呼び出すために、しようとする定義の時間ですでに診断の原因となります~B

もう一つの違いは、デストラクタとメンバのデストラクタを暗黙的な呼び出しの定義を中心と。このスマートポインタのメンバーを考慮して

struct C;
struct A {
    auto_ptr<C> a;
    A();
};

の型のオブジェクトを仮定Cのの定義のコンストラクタが作成されます.cppまた、構造体の定義を含むファイル、 A 。さて、あなたは構造体を使用する場合struct C; struct A { auto_ptr<C> a; A(); ~A(); // defined as ~A() { } in .cpp file, too }; 、および破壊を必要とするboost::shared_ptrオブジェクトは、コンパイラは、念のため、上記のようにデストラクタの暗黙的な定義を提供します。それはデストラクタが暗黙的にauto_ptrのオブジェクトのデストラクタを呼び出します。そして、それはそれは保持を指すポインタを、削除されますmemsetオブジェクト - の定義を知らずに !それが登場ここでコンストラクタの構造体のファイルが定義されます。

これは実際にpimplイディオムを実装する一般的な問題です。解決策はここにデストラクタを追加し、それの空の定義を提供することです構造体ファイル、 定義されます。同時に、そのメンバのデストラクタを呼び出すと、それは、構造体の定義を知っている 、正しくそのデストラクタを呼び出すことができます。

注意してくださいその問題を持っていない:これは、代わりに完全な型をコンストラクタは、特定の方法で呼び出される必要があります。

それが現在のC + +での違いはもう一つのポイントは、ときに使用する方法ですとユーザーがそのようなオブジェクトの友達は、デストラクタを宣言した。このような種類のPODをもう(プレーン古いデータ)、およびこれらのビットにコピーすることは許可されませんされていません。注:実際に必要に応じていないこと、この制限はありません - 次のC + +のバージョンは、この上の状況を改善し、他の重要な変更が行われないようにように静止画に限り、このような型をビットのコピーをすることができます。


あなたはコンストラクタを求めたので:さて、これらとほぼ同じものに該当する。そのコンストラクタもデストラクタに暗黙的な呼び出しが含まれて注意してください。 auto_ptrはのようなもので、これらの呼び出し(たとえ実際には実行時に行われていない - 純粋な可能性がすでにここに)デストラクタと同じ害を及ぼすだろう事項とするとき、コンストラクタで何かがスローされますが起こる - コンパイラは、デストラクタを呼び出すために必要ですメンバーのこの答えは、コンストラクタのデフォルトの定義の暗黙の使用していますか。

また、同じことが可視性とPODness真の私は、デストラクタ上記について言われて。

1つの重要な違いは、初期化についてです。ユーザーを配置する場合のコンストラクタを宣言し、あなたのタイプは、メンバーの値の初期化を受信しない


2)

はい、空のデストラクタが自動的に生成されたものと同じです。私はいつも通り、コンパイラが自動的に生成させるている。私はそれが必要な何かを異常行うには:makeは、仮想、またはプライベート、と言うneed unless explicitlyデストラクタを指定することはないと思う。


3)

あなたはクラスの定義されて空のデストラクタは、ほとんど同様の意味を持ってに関しては、すべてではないです。

具体的には、暗黙的に定義デストラクタ
1))はインライン公益委員がない(あなたは、インライン
2)デストラクタ(必要に応じ組合のことができる単純な型を作るように表される、あなたのことはできません)
3)例外仕様(スロー()、あなたはない)を持つ


4)

私は最高の空の宣言を配置するというだろうという、それは将来のメンテナをそれは監督ではなかったようで、あなたは本当に、デフォルトのいずれかを使用することを意味した。


5)

私はダビデに、私はそれは一般的にお勧めの仮想デストラクタ、すなわちを定義することだと思います除いて同意

virtual ~Foo() { }

あなたのFooクラスから継承する人々はそのデストラクタが呼び出されることはありません気づいていない可能性がありますので、仮想デストラクタを逃し、メモリリークが発生する可能性があります!


6)

定義が参照できるので、空の定義は結構です

virtual ~GameManager() { };
空の宣言は、一見外見が似ている
仮想〜GameManager(); 
まだエラーが定義のために仮想デストラクタのない招待恐ろしい
Undefined symbols:
  "vtable for GameManager", referenced from:
      __ZTV11GameManager$non_lazy_ptr in GameManager.o
      __ZTV11GameManager$non_lazy_ptr in Main.o
ld: symbol(s) not found