如果使用基指针声明,为什么简单的析构函数不会删除派生对象 [英] Why simple destructor does not delete the derived object if declared using base pointer

查看:89
本文介绍了如果使用基指针声明,为什么简单的析构函数不会删除派生对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

int main()
{

    Base *p = new Derived;
    delete p;
    return 0;
}

我有些困惑,为什么在这里删除p不会删除派生对象?是这样派生对象包含基类型的子对象,而指针 p 实际上指向派生对象的基础部分(子对象)。因此,当 delete p 运行时,它将只能删除派生类对象的基类部分,并且它将具有导出部件销毁的未定义行为。这将导致内存泄漏。因此,为了避免内存泄漏,我们需要设法调用对象的基础和派生析构函数以避免内存泄漏!这样吗?这就是我们需要虚拟析构函数的原因吗?因此,当基础析构函数是虚拟的时,派生类析构函数将覆盖基类的析构函数(它是虚拟的)。请澄清??

I have some confusion, why deleting p here won't delete the derived object ? Is it so that the derived object contains the sub-object of base type and pointer p is actually pointing to the base part ( sub-object) of the derived object. So when delete p is run it will only be able to delete the base class part of the object of the derived class and it will have undefined behavior for the derived part destruction. This will cause memory leaks. So to avoid memory leakage we need to manage to call both base and derived destructors of the object to avoid memory leakage! Is this so ? Is that the reason we need Virtual destructors for ?? So that when the base destructor is virtual, the derived class destrutor would override the base class's destructor (which is virtual). Please clarify??

推荐答案

如果你问基类没有虚拟析构函数时的行为,那么你的困惑是事实上你已经对这个删除表达式的行为有一些预先设想的误解

If you are asking about the behavior in situation when base class has no virtual destructor, then your confusion is stemming for the fact hat you already have a number of pre-conceived misconceptions about the behavior of this delete expression


它只能删除对象的基类部分

"It will only be able to delete the base class part of the object"

这会导致内存泄漏

这些都没有任何意义。这里没有内存泄漏,并且没有任何确定性能够删除它的基类部分。

None of this makes any sense. There's no memory leaks here, and there's nothing as deterministic as being able to "delete the base class part" of it.

如果基类没有虚拟析构函数的行为这些代码只是 undefined 。未定义的行为可以表现出很多种不同的方式,包括但不限于不正确的析构函数调用,不正确的运算符删除选择,堆损坏,是的,内存泄漏,直接和间接的。在这种情况下,有许多不同的东西可以搞砸。不只是一些内存泄漏,因为流行的误解让人们相信。 (关于内存泄漏的热门话题来自哪里。有人知道吗?)

If the base class has no virtual destructor the behavior of such code is simply undefined. There are quite a few different ways that undefined behavior can manifest itself, including but not limited to improper destructor call, improper operator delete selection, heap corruption and, yes, "memory leaks", both direct and indirect. There are many different things that can get screwed up in this case. Not just some "memory leaks", as the popular misconception makes people believe. (Where does that popular bit about "memory leaks" come from. Does anyone know?)

所以,你需要虚拟析构函数。如果一个人决定全力以赴地详细分析它,那么你需要的完整原因列表可能会很长。但无论如何,这是一个实现细节。如果不将它与特定的实现联系起来,没有具体的解释。

So, you do need virtual destructor here. And the full list of reasons you need it can get quite long, if one decides to make a full effort to analyze it exhaustively. But in any case, this is an implementation detail. There's no specific explanation of what will really happen without tying it to a specific implementation.

至于概念的解释......总是最明显的一个:它当然,必须调用正确的析构函数才能执行适当的销毁。即使我们只是考虑用户定义的销毁步骤(即用户在派生类析构函数中明确写入的内容),我们仍然需要析构函数多态来正确调用那个析构函数。

As for the "conceptual" explanation... There's always the most obvious one: it is, of course, necessary to invoke the proper destructor in order to performs the proper destruction. Even if we simply limit out consideration to user-defined destruction steps (i.e. what the user explicitly wrote in their derived-class destructor), we still need destructor polymorphism to properly invoke that destructor.

但是,还有许多其他内部原因。例如,在典型的实现中,选择适当的运算符delete 进行原始内存释放也会依赖于析构函数的虚拟性(参见这里,例如)

However, there are also a number of other internal reasons. For example, in a typical implementation selection of the proper operator delete for raw memory deallocation also piggybacks on the virtuality of the destructor (see here, for example)

这篇关于如果使用基指针声明,为什么简单的析构函数不会删除派生对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆