0
class A
{
public:
    int i;
    ~A()
    {   
        std::cout << "~A" << std::endl;
    }   
};

class B: public A
{
public:
    int k;
    ~B()
    {   
        std::cout << "~B" << std::endl;
    }   
};

int main(int argc, char* argv[])
{
    A* p = new B();
    delete p;
    return 0;
}

ベースデストラクタは仮想ではなく、理由はわかっていますが、上記はメモリリークを引き起こしません。

しかし、これは未定義の動作ですか?

ベースデストラクタが非仮想であっても、派生クラスが他の動的データを指していなければ、メモリリークは発生しないと思いますか?

4

2 に答える 2

7

はい、そうですclassデストラクタのない基本クラスへのポインタを介して派生したオブジェクトを削除することは、virtual教科書 UB です。

5.3.5/3:

最初の選択肢 (オブジェクトの削除) では、オペランドの静的型がその動的型と異なる場合、静的型はオペランドの動的型の基本クラスであり、静的型は仮想デストラクタを持つか、動作が未定義です。 . 2 番目の選択肢 (配列の削除) では、削除するオブジェクトの動的な型がその静的な型と異なる場合、動作は未定義です 73)。

これは未定義の動作であるため、コードがリークするかどうかを推測しても意味がありません。結果を予測するのではなく、コードを修正してみてください。

于 2012-05-27T15:49:31.983 に答える
4

はい、静的型 (ここでは) は動的型 (あなたの例でAは) とは異なり、デストラクタがないため、UB です。Bvirtual

5.3.5/2 (C++11 では 5.3.5/3):

最初の選択肢 (オブジェクトの削除) では、オペランドの静的型がその動的型と異なる場合、静的型はオペランドの動的型の基本クラスであり、静的型は仮想デストラクタを持つか、動作が未定義です。 .

于 2012-05-27T15:51:00.430 に答える