以多态方式删除对象

时间:2012-04-16 15:55:05

标签: c++ virtual-destructor

Base* optr=new Derived();

delete optr;

我知道如果Base类有一个非虚析构函数,在删除optr指针时只会调用~Base()析构函数。但是我发现即使没有~Dedived()析构函数被调用,派生对象占用的内存也被释放了。所以我的问题是,一个对象可以在不调用它的析构函数的情况下被释放吗?

如果答案是,如果我的Derived类不包含任何动态分配的变量,我是否可以使用非虚拟析构函数,所以我不在乎它是否被调用?

5 个答案:

答案 0 :(得分:4)

从标准C ++的角度来看,答案很简单:结果是未定义的行为,所以你得到的是完全不可预测的

我有点不解为什么你还在乎。如果您可以从类中消除 all 虚拟函数,则每个实例都会变小(按vtable指针的大小)。使用诸如基类这样的东西很少有意义 - 为了使用作为基类是合理的,你几乎需要在基础中至少有一个虚函数来覆盖派生类。一旦你有了虚拟功能(任何虚拟功能),添加更多功能基本上是免费的 - 通过添加更多虚拟功能,对象不会变得更大。

直接回答你的问题:是的,可以在不调用析构函数的情况下释放内存。真正的问题是当你实现这一目标时会发生什么(并且对这个问题没有答案)。

答案 1 :(得分:2)

关于未定义行为的事情是,有时似乎有效

如果基类析构函数不是虚拟的,标准并没有说你的程序必须失败,它说当析构函数 虚拟时它必须工作。 / p>

答案 2 :(得分:1)

如果派生类没有添加任何成员,那么可能能够在没有虚拟析构函数的情况下离开。内存占用将是相同的,并且成员将在基类析构函数中被销毁。但是,标准并不保证这一点,您将受到编译器实现的支配。

答案 3 :(得分:1)

有两个不同的东西:调用对象析构函数,释放内存。

标准堆规范不要求您在释放时传递内存块大小。也就是说,堆实现应该自己推断出内存块大小。

因此 - 。如果Derived不包含必须通过适当方式销毁的额外内容(例如在堆上分配的内存,文件句柄等) - 您不需要虚拟析构函数。

答案 4 :(得分:0)

请看这里:Virtual destructor