1

Base* optr=new Derived();

delete optr;

I know that if Base class has a non-virtual destructor, only ~Base() destructor is going to be called when deleting optr pointer. But I found out that even without ~Derived() destructor being called the memory that was taken by the Derived Object was freed. So my question is can an object get freed without calling it's destructor?

If the answer is yes, can I use a non-virtual destructor if my Derived class does not contain any dynamically allocated variables so I don't care if it did not get called?

4

5 回答 5

4

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

我有点不明白你为什么要关心。如果您可以从类中消除所有虚函数,则每个实例都会变小(按 vtable 指针的大小)。但是,使用基类这样的东西很少有意义——为了明智地用作基类,您几乎需要在基类中至少有一个虚函数来覆盖派生类。一旦你有了一个虚函数(任何虚函数),添加更多实际上是免费的——对象不会因为添加更多虚函数而变得更大。

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

于 2012-04-16T16:04:54.770 回答
2

未定义行为的问题是,有时它似乎有效

该标准并没有说如果基类析构函数不是虚拟的,您的程序就必须失败,它说当析构函数是虚拟的时它必须工作

于 2012-04-16T16:04:47.423 回答
1

如果派生类不添加任何成员,您也许可以在没有虚拟析构函数的情况下逃脱。内存占用是相同的,并且成员都将在基类析构函数中被销毁。但是,标准并不能保证这一点,您将受制于编译器的实现。

于 2012-04-16T16:02:00.053 回答
1

有两件不同的事情:调用对象析构函数和释放内存。

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

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

于 2012-04-16T16:02:55.617 回答
0

看这里:虚拟析构函数

于 2012-04-16T15:57:46.273 回答