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的基类的指针删除派生对象是教科书 UB。virtual

5.3.5/3:

在第一种选择(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义. 在第二种选择(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。73)

因为它是未定义的行为,所以猜测代码是否会泄漏并没有任何意义。只是尝试修复代码而不是预测结果。

于 2012-05-27T15:49:31.983 回答
4

是的,因为静态类型(这里是A)不同于动态类型(B在你的例子中)并且没有virtual析构函数,它是一个 UB。

5.3.5/2(C++11 中的 5.3.5/3):

在第一种选择(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义.

于 2012-05-27T15:51:00.430 回答