Base* optr=new Derived();
delete optr;
我知道如果Base类有一个非虚析构函数,在删除optr
指针时只会调用~Base()析构函数。但是我发现即使没有~Dedived()析构函数被调用,派生对象占用的内存也被释放了。所以我的问题是,一个对象可以在不调用它的析构函数的情况下被释放吗?
如果答案是是,如果我的Derived类不包含任何动态分配的变量,我是否可以使用非虚拟析构函数,所以我不在乎它是否被调用?
答案 0 :(得分:4)
从标准C ++的角度来看,答案很简单:结果是未定义的行为,所以你得到的是完全不可预测的
我有点不解为什么你还在乎。如果您可以从类中消除 all 虚拟函数,则每个实例都会变小(按vtable指针的大小)。使用诸如基类这样的东西很少有意义 - 为了使用作为基类是合理的,你几乎需要在基础中至少有一个虚函数来覆盖派生类。一旦你有了虚拟功能(任何虚拟功能),添加更多功能基本上是免费的 - 通过添加更多虚拟功能,对象不会变得更大。
直接回答你的问题:是的,可以在不调用析构函数的情况下释放内存。真正的问题是当你实现这一目标时会发生什么(并且对这个问题没有答案)。
答案 1 :(得分:2)
关于未定义行为的事情是,有时似乎有效。
如果基类析构函数不是虚拟的,标准并没有说你的程序必须失败,它说当析构函数 虚拟时它必须工作。 / p>
答案 2 :(得分:1)
如果派生类没有添加任何成员,那么可能能够在没有虚拟析构函数的情况下离开。内存占用将是相同的,并且成员将在基类析构函数中被销毁。但是,标准并不保证这一点,您将受到编译器实现的支配。
答案 3 :(得分:1)
有两个不同的东西:调用对象析构函数,释放内存。
标准堆规范不要求您在释放时传递内存块大小。也就是说,堆实现应该自己推断出内存块大小。
因此 - 是。如果Derived
不包含必须通过适当方式销毁的额外内容(例如在堆上分配的内存,文件句柄等) - 您不需要虚拟析构函数。
答案 4 :(得分:0)
请看这里:Virtual destructor