11
#include <iostream> 
using namespace std; 
class base 
{ 
    int a; 
public: 
    base() {a =0;} 
}; 
class derv :public base 
{ 
    int b; 
    public: 
    derv() {b =1;} 
}; 
int main() 
{ 
    base *pb = new derv(); 
    delete pb; 
} 

私はdervクラスに仮想デストラクタを持っていませんが、dervオブジェクトの基本部分だけを削除しますか?仮想デストラクタなしでメモリリークが発生する可能性がありますか?

+0

仮想デストラクタを必要とする基本クラスです。 – Yuushi

+0

@神秘:ジェームズはこれを持っています。 – Puppy

+0

@James、あなたは基本クラスにも仮想関数はないと言っていますが、基本クラスを継承したい場合は仮想デストラクタを必要としていますか? – Alok

答えて

19

場合があります。

baseには仮想デストラクタがないため、コードは未定義の動作を示します。何かが起こるかもしれません。期待どおりに動作するように見えるかもしれません。メモリがリークする可能性があります。プログラムがクラッシュする可能性があります。それはあなたのハードドライブをフォーマットするかもしれません。

引用が要求されました。スカラーdelete発現(すなわち、ないdelete[]発現)のために、C++ 11§5.3.5/ 3状態:

オブジェクトの静的な型を削除する場合は、そのダイナミック型とは異なります静的型は、削除されるオブジェクトの動的型の基本クラスでなければならず、 静的型は仮想型の破棄子を持つか、振る舞いは未定義です。

静的タイプ(base)はダイナミック型(derv)とは異なり、静的な型は、仮想デストラクタを持たないので、動作は未定義です。

+2

ベースの仮想デストラクタがないということは、派生クラスのデストラクタで指定されたカスタム終了が実行されないことを意味します。オブジェクトのメモリは、依然として正しく割り振り解除されます。 ( 'base'のデストラクタは非仮想で定義されていれば呼び出されます)。 – Xion

+6

@ Xion:本当に。動作は未定義です。すべてのベットはオフです。プログラムの動作について確実に言えることはありません。 –

+2

参考、どうぞ! – wilhelmtell

-1

コードにメモリリークはありません。派生クラスのデストラクタでメモリを解放する必要がある場合は、メモリリークが発生していました。

+6

動作は未定義です。すべてのベットはオフです。プログラムの動作について確実に言えることはありません。 –

-1

動的に作成されるメンバー変数がないため、ソースコードにはメモリリークはありません。 「B」は、動的に作成されるため、出力がされる。この場合

#include <iostream> 
using namespace std; 
class base 
{ 
    int a; 
public: 
    base() {a =0;} 
    ~base() 
    { 
     cout<<"\nBase Destructor called"; 

    } 
}; 
class derv :public base 
{ 
    int *b; 

    public: 
    derv() { b = new int;} 
    ~derv() 
    { 
     cout<<"\nDerv Destructor called"; 
     delete b; 
    } 
}; 
int main() 
{ 
    base *pb = new derv(); 
    delete pb; 
} 

、メモリリークが存在する。この場合

Base Destructor called 

ケース1以下の変形例を考えてみ'delete'キーワードを使用して削除する必要がある 'new'を使用します。 dervデストラクタは呼び出されていないので、削除されないので、メモリリークがあります。この場合、DERVのデストラクタleak.because全く記憶が呼び出されていないとbが取得されている

Derv Destructor called 
Base Destructor called 

、2出力がされる場合

#include <iostream> 
using namespace std; 
class base 
{ 
    int a; 
public: 
    base() {a =0;} 
    virtual ~base() 
    { 
     cout<<"\nBase Destructor called"; 

    } 
}; 
class derv :public base 
{ 
    int *b; 

    public: 
    derv() { b = new int;} 
    ~derv() 
    { 
     cout<<"\nDerv Destructor called"; 
     delete b; 
    } 
}; 
int main() 
{ 
    base *pb = new derv(); 
    delete pb; 
} 

は、以下のケース2を考えてみましょう削除されました。

Destructorは、派生クラスオブジェクトを指している基本クラスポインタを削除するときに派生クラスのデストラクタが呼び出されるように、基本クラスのVirtualとして定義できます。

「派生クラスが動的に作成されたメンバーを持つ場合、デストラクタは仮想でなければなりません」と言うことができます。

+1

動作は未定義です。すべてのベットはオフです。プログラムの動作について確実に言えることはありません。 –

+1

@JamesMcNellis:上のコードでは、派生クラスでメモリの割り当てを持つ仮想デストラクタを持つ必要があります。それ以外の場合は、メモリリークが発生します。 –

関連する問題