是否调用析构函数明确地彻底摧毁一个对象?(Does calling a destructor exp

2019-06-24 00:38发布

如果我显式调用析构函数(myObject的。〜对象())这是否已向我保证对象将适当销毁(调用所有子析构函数)?

好了一些代码:

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

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

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

我知道我可以只删除对象,但我不想。 我想保留所分配的内存得心应手作为一种重要的优化。

谢谢!

Answer 1:

答案是......几乎总是。

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

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

然而,第二共享库未被重新编译。 这意味着,它不知道新添加的虚拟对象的定义。 删除的从简单的所谓的自由第二共享库调用,并没有调用虚析构函数链。 结果是一个讨厌的内存泄漏。



Answer 2:

是。 但圣烟,你确定吗? 如果是的话,我会用安置new来构建你Widget 。 使用放置new ,然后显式调用析构函数是可以接受的,一旦发现异常,成语。

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

此外,也许更重要的是,你会那么做放置new “正常”,而不是这种混合正规new /放置new的解决方案。 我并不是说,它不会工作,我只是说这是一个相当啊, 创造性地解决你的记忆问题。



Answer 3:

是的,析构函数,即使明确提出,将正确地破坏它的子对象。

你似乎意识到,这是一个罕见的动作做,但也许作为一个很好的测试和记录库的一部分,它可能是有用的。 但是,文件(和配置文件),它,因为即使它是有效的,安全的,每一个维护者(包括你)永远不会感到舒服。



Answer 4:

是的,它会调用所有的孩子析构函数,因此将作为你期待。

析构函数仅仅是一个函数毕竟,它只是恰巧,对象被删除时它被调用。

因此,如果您使用这种方法要注意的是:

#include <iostream>

class A
{
public: 
    A(){};
    ~A()
    {
        std::cout << "OMG" << std::endl;
    }
};

int main()
{
    A* a = new A;
    a->~A();
    delete a;
    return 0;
}

output:
OMG
OMG 

调用析构函数删除时,实际被调用的对象上的第二次,所以如果你在你的析构函数删除指针,确保将它们设置为0,从而使第二调用析构函数什么都不会发生(如删除空指针什么都不做)。



Answer 5:

请妥善保存自己的一些真正的头痛和使用升压对象池 ,这听起来像你的源/汇模式的现有的实现。 这将分配大块的内存,它们切成为对象的正确尺寸并返还给你(调用构造函数后)。 当您删除的对象,他们称他们的析构函数,并投入对象的链接列表进行再利用。 它会不断地自动收缩,并确保你的对象实例往往是并拢在内存中。

如果不出意外,这是放置新的,明确的使用,你可以学习构造的一个很好的例子实施。



Answer 6:

是。 析构函数调用LIFO顺序,那么基类的析构函数的任何成员的析构函数,有没有办法阻止它调用析构函数,这些*。 对象堆被保证放松。

初始化和结束是从内存分配和释放的下分离++正是因此,在特定情况下出现的时候,有一个明确的语法中的应用程序员可以表达自己的意图编译器。

编辑:

  • 我想,通过调用中止()或longjmp的()一个能,实际上防止所述构件和基类析构函数的运行。


Answer 7:

运行析构函数没有被物体破坏占用的内存 - delete运算符做到这一点。 但是请注意,析构函数可以删除“子对象”和它们的内存被释放,按往常一样。

您需要在放置新读了/删除,因为这可以让你控制内存分配和构造时/析构函数运行。

看到这里一点点信息:

http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9


Answer 8:

STL容器做到这一点。 事实上,一个STL分配器必须提供调用对象的析构函数(allcators还提供解除分配的方法来解除分配用于保存一个对象的内存),一个破坏方法。 然而,从Stroustrup的建议(C ++编程语言 10.4.11)是

注意析构函数的显式调用......应尽可能避免。 偶尔,他们是必不可少的。 ...新手应该三思而后行显式调用析构函数之前这样做之前也问一个更有经验的同事。



Answer 9:

调用析构函数是罚款。 然而,当心你调用它的类型。 如果该类型没有(没有继承)虚析构函数,你可能会得到意外的行为。

此外,如前所述,析构函数不会释放任何记忆,但我想这是要摆在首位手动调用它的原因。

另外,除非我错了,请手动调用析构函数是你,如果你用放置新调用构造函数的唯一选择。



Answer 10:

为什么要毁掉它呢? 只要写在记忆? 你想要的逻辑来执行正常处理释放资源? 我要强调,这是语言的滥用,而不是一个好主意状态。



Answer 11:

我会考虑你想要的特殊分配和释放行为的对象压倒一切的新的 - 毕竟这就是它是。 正常新的显式调用析构函数的混合方案听起来像未来头痛的良方。 对于初学者来说,任何内存泄漏检测的策略是要抛出的路要走。



文章来源: Does calling a destructor explicitly destroy an object completely?