调用析构函数是否完全破坏对象?

如果我明确地调用了一个析构函数(myObject。〜Object()),这是否会保证该对象将被适当销毁(调用所有子析构函数)?

确定一些代码:

class Object
{
   virtual ~Object()
   {}
};

class Widget : public Object
{
   virtual ~Widget()
   {}
};

...
Object* aWidget = new Widget(); //allocate and construct
aWidget->~Object(); //destroy and DON'T deallocate

我知道我可以删除对象,但我不想。 我希望保持分配的内存方便,作为一个重要的优化。

谢谢!


答案是...几乎总是。

如果你的对象有一个非虚拟析构函数,然后再分类以添加需要释放的子元素,那么调用对象基类的析构函数将不会释放子元素。 这就是为什么你应该总是声明析构函数是虚拟的。

我们有一个有趣的例子,其中两个共享库引用了一个对象。 我们改变了定义来添加需要释放的子对象。 我们重新编译了包含对象定义的第一个共享库。

但是,第二个共享库没有重新编译。 这意味着它不知道新添加的虚拟对象定义。 从第二个共享库调用的Delete只是简单地称为free,并没有调用虚拟析构函数链。 结果是令人讨厌的内存泄漏。


是。 但圣洁的吸烟者,你确定吗? 如果是的话,我会使用placement new来构建你的Widget 。 使用placement new并明确调用析构函数是一种可接受的,如果不寻常的习惯用法。

编辑 :考虑手动分配内存,而不是使用new分配第一个对象,然后重新使用它的内存。 这可以让你完全控制内存; 例如,您可以一次分配大块,而不是为每个Widget分配单独的内存块。 如果记忆真的是如此稀缺的资源,这将是公平的节省。

此外,也许更重要的是,您将会进行new “正常”放置,而不是这种混合定期new /放置new解决方案。 我并不是说这不会起作用,我只是说这是一个相当有创意的解决方案,以解决您的记忆问题。


是的,即使在明确调用的情况下,析构函数也会正确地销毁其子对象。

正如你似乎意识到的那样,这是一个罕见的行动,但也许作为经过充分测试和记录的库的一部分,它可能是有用的。 但是,即使它是有效且安全的,每个维护者(包括你)都不会对它感到满意,因此文档(和配置文件)就是如此。

链接地址: http://www.djcxy.com/p/82807.html

上一篇: Does calling a destructor explicitly destroy an object completely?

下一篇: Are Structs always stack allocated or sometimes heap allocated?