这是未定义的行为吗?

时间:2012-05-27 15:48:33

标签: c++ standards

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;
}

虽然基础析构函数不是虚拟的但上面不会导致内存泄漏,我知道原因。

但这是否是未定义的行为?

如果派生类没有指向其他动态数据,即使基础析构函数是非虚拟的,也不会有内存泄漏?

2 个答案:

答案 0 :(得分:7)

是的。通过指向没有class析构函数的基类的指针删除派生virtual的对象是教科书UB。

<强> 5.3.5 / 3:

  

在第一个替代(删除对象)中,如果是静态类型的   操作数与其动态类型不同,静态类型应为a   操作数的动态类型的基类和静态类型   有一个虚拟析构函数或行为未定义。在第二   替代(删除数组)如果要对象的动态类型   删除与其静态类型不同,行为未定义.73)

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

答案 1 :(得分:4)

是的,因为静态类型(此处为A)与动态类型(示例中为B)不同,并且没有virtual析构函数,所以它是UB。

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

  

在第一个替代(删除对象)中,如果操作数的静态类型与其动态类型不同,则   static类型应该是操作数的动态类型的基类,静态类型应该是虚拟的   析构函数或行为未定义。