如果我呼叫一个析构明确(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

我知道我可以只删除的对象,但是我不想。我想要保留所分配的存储方便作为一个重要的优化。

谢谢!

有帮助吗?

解决方案

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

如果您的对象具有非虚拟析构函数,然后进行子类化以添加需要释放的子元素...则在对象基类上调用析构函数将不会释放子元素。这就是为什么你应该总是声明析构函数是虚拟的。

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

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

其他提示

是。但圣洁的烟雾,你确定吗?如果是这样,我会使用展示位置new 来构建您的Widget。使用placement <=>然后显式调用析构函数是一种可接受的,如果不寻常的习惯用法。

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

此外,或许更重要的是,您可能正在进行<=> <!>“通常<!>”,而不是这种混合常规<=> / placement <=>解决方案。我不是说它不起作用,我只是说这是一个相当的,啊,创意解决你的记忆问题。

是的,析构函数,即使被明确调用,也会正确地破坏它的子对象。

正如您似乎意识到的那样,这是一项罕见的行动,但也许作为经过良好测试和记录的库的一部分,它可能会有用。但是文档(和简介)虽然它是有效和安全的,但每个维护者(包括你)都不会对它感到满意。

是的,它将调用所有子析构函数,以便它可以按预期工作。

析构函数毕竟只是一个函数,当对象被删除时它就会被调用。

因此,如果你使用这种方法,请注意:

#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 

在对象上实际调用delete时第二次调用析构函数,因此如果在析构函数中删除指针,请确保将它们设置为0,以便第二次调用析构函数时不会发生任何事情(如删除空指针什么都不做。)

请为自己省去一些真正的麻烦并使用 Boost对象池,听起来像是源/接收器模式的现有实现。它将分配大块内存,将它们切成适合您对象的大小并将它们返回给您(在调用构造函数之后)。当您删除对象时,它们会调用它们的析构函数,并将它们放入对象的链接列表中以供重用。它会自动增长和缩小,并确保对象的实例在内存中相互靠近。

如果不出意外,它是一个很好的示例实现,可以放置新的和显式使用的构造函数。

是的。一析构,呼吁任何成员析构在后进先出订单,然后基类析构,有没有办法 防止 它呼吁这些析构*.对象堆是有保障的设施。

初始化和最终确定分离的记忆分配和释放在C++正是这样,在特殊情况下产生,有一个明确的语法中的应用程序员可以表达他或她意图的编译器。

编辑:

  • 我想,通过调用中止()或值指出控制()一个可能的,事实上,防止件和基类析构运行。

运行析构函数不会释放被破坏对象使用的内存 - 删除操作符会这样做。但是请注意,析构函数可能会删除<!>“子对象<!>”;他们的记忆将按照惯例释放。

您需要阅读放置新/删除,因为这允许您控制内存分配以及构造函数/析构函数运行时。

请点击此处获取一些信息:

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

STL容器这样做。实际上,STL分配器必须提供一个调用对象析构函数的destroy方法(allcators还提供一个deallocate方法来释放用于保存对象的内存)。但是,Stroustrup( C ++编程语言 10.4.11)的建议是

  

请注意,应尽可能避免显式调用析构函数。有时,它们是必不可少的。 ......在明确调用析构函数之前,新手应该三思而后行,并在此之前询问更有经验的同事。

调用析构函数很好。但是,请注意您正在调用它的类型。如果该类型没有(没有继承)虚拟析构函数,则可能会出现意外行为。

另外,如上所述,析构函数不释放任何内存,但我想这就是你想首先手动调用它的原因。

另外,除非我弄错了,否则如果你使用placement new来调用构造函数,那么手动调用析构函数是唯一的选择。

为什么要毁掉它?只是写在记忆中?您是否希望执行逻辑以优雅地处理释放资源?我将强调说这是对语言的滥用而不是一个好主意。

我会考虑为你想要特殊分配和释放行为的对象覆盖new - 毕竟这就是它的用途。正常的新的和明确调用的析构函数的混合方案听起来像是未来头痛的秘诀。首先,任何内存泄漏检测策略都会被抛弃。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top