2

仮想デストラクタと、ヒープにスペースを割り当てるという概念を理解しているかどうかはよくわかりません。次の例を見てみましょう。

class Base
{
public:
    int a;
};

class Derived : public Base
{
public:
    int b;
};

こういうことをしたら、と想像します。

Base *o = new Derived;

8 バイト (またはシステムで必要な 2 つの整数) がヒープに割り当てられます。これは次のようになります。| | b | ...

今私がこれを行うと:

delete o;

「delete」は、ヒープからすべてを削除するために、実際にはどのタイプの o であるかをどのように認識しますか? Base 型であると想定する必要があるため、ヒープから a のみを削除する必要があると思います (b がオブジェクト o に属しているかどうかを確認できないため)。b | ...

b はヒープに残り、アクセスできなくなります。

次のことを行います。

Base *o = new Derived;
delete o;

本当にメモリリークを引き起こしますか?ここで仮想デストラクタが必要ですか? または、delete は、o が実際には基底クラスではなく、派生クラスであることを認識していますか? もしそうなら、それはどのように機能しますか?

みんなありがとう。:)

4

3 に答える 3

1

削除されるオブジェクトのサイズに問題はありません - それは知られています。仮想デストラクタによって解決される問題は、次のように示すことができます。

class Base
{
public:
    Base() { x = new char[1]; }
    /*virtual*/ ~Base() { delete [] x; }

private:
    char* x;
};

class Derived : public Base
{
public:
    Derived() { y = new char[1]; }
    ~Derived() { delete [] y;}
private:
    char* y;
};

それから:

Derived* d = new Derived();
Base* b = new Derived();

delete d;   // OK
delete b;   // will only call Base::~Base, and not Derived::~Derived

2 回目の削除では、オブジェクトが適切にファイナライズされません。virtualキーワードのコメントが外されている場合、2 番目のdeleteステートメントは期待どおりに動作し、Derived::~Derivedと共に呼び出されBase::~Baseます。

コメントで指摘されているように、厳密に言うと、2 番目の削除は未定義の動作をもたらしますが、ここでは仮想デストラクタについて指摘する目的でのみ使用されています。

于 2013-08-04T20:13:56.167 に答える