繁体   English   中英

使用非虚拟析构函数和Base类指针释放整个对象吗?

[英]Is the whole object freed with a non-virtual destructor and a Base class pointer?

如果Base类没有虚拟析构函数(例如为了避免vtable条目)并且Derived类只有基本属性,那么当删除Base类的指针时,是否释放new分配的所有内存? 我知道Derived类的析构函数不会被调用,但我想知道整个对象分配的内存是否会被释放? 我还假设在Derived指针上调用delete将释放整个内存空间。

另外,如果它没有释放内存的Derived类部分,它是如何在相同的情况下工作但是在Base类中使用虚拟析构函数, 知道要释放多少内存

例:

class Base {
  public:
    int a;
    int b;
   Base() {}
  ~Base() {}
};

class Derived : public Base {
  public:
    int c;
    int d;
    Derived() {}
    ~Derived() {}
};

int main() {
  Base *p = new Derived();
  delete p; // is memory allocated for Derived freed?
  return 0;
}

这是未定义的行为,所以任何事情都可能发生。 从标准[expr.delete]引用:

在第一个备选(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除的对象的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义。

虽然它的工作原理是实现的细节,但典型的实现可能会自动覆盖派生类中的析构函数,并在那里实现内存的释放。 请注意,必须在基类中定义虚拟析构函数,以便实现可以在虚拟表中保留条目。

从形式上讲,这是未定义的行为,因此您无法保证释放内存,或者确实您的程序特别做了什么。 它可能会格式化您的硬盘。 它可能不会。 在实践中,在这种情况下可能会释放内存 - 但如果你依赖它就会愚蠢,而你不应该这样做。 就这么简单。

从技术上讲,答案是'未知'。 删除从指向没有虚析构函数的base的指针派生的指针是未定义的行为。

实际上,大多数实现都无法正确删除派生对象中的内容。

编辑:我错了:草案标准的重要散文,强调我的:第5.3.5节

3在第一个备选(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除的对象的动态类型的基类,静态类型应为有一个虚拟析构函数或行为未定义。 在第二个备选(删除数组)中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。

内存很有可能被正确释放。 仅仅因为标准不保证这并不意味着它不起作用。 很难看出它会如何失败。

在您描述的特定情况下,当您没有虚拟析构函数时,将释放派生类对象使用的所有内存。 (如果使用非虚拟析构函数总是导致派生类泄漏内存,我认为该语言不允许从使用它们的类继承!)

记住,DESTRUCTOR并不能释放内存; “删除”释放内存。 析构函数只是一个通过删除获得CALLED的函数。

Blah blah blah blah可扩展性等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等。你知道我的意思。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM