2012-05-27 51 views
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; 
} 

上面不会导致内存泄漏虽然碱析构函数不是虚拟和我知道的原因。这是未定义的行为吗?

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

说也不会有内存泄漏如果派生类不指向其它动态数据,即使基地析构函数非虚拟?

回答

7

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

5.3.5/3:

在第一种方式(删除对象),如果静态类型 操作数是从它的动态类型不同,静态类型应是 基操作数的动态类型的类和静态类型应具有虚拟析构函数或行为未定义。在第二个备选 (删除数组)如果动态类型的对象是从它的静态类型 删除不同的,那么行为是undefined.73)

由于它是未定义的行为,它并没有真正使感觉猜测代码是否会泄漏。只是试图修复代码而不是预测结果。

+0

你有没有遇到这样的代码(派生类不指向动态数据),导致漏气? –

+0

@new_perl是的,但是派生类析构函数也释放了一些内存。 –

+0

这肯定会发生。但我在谈论派生类析构函数不需要明确释放任何东西的情况。 –

4

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

5.3.5/2(在5.3.5/3 C++ 11):

在第一种方式(删除对象),如果静态类型的操作数是从它的动态类型不同,静态类型应该是操作数的动态类型的基类,并且静态类型应该具有虚拟的析构函数或行为未定义。