如果我显式地调用析构函数(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
Run Code Online (Sandbox Code Playgroud)
我知道我可以删除该对象,但我不想这样做.我希望将分配的内存作为一项重要的优化保留.
谢谢!
the*_*jxc 16
答案是......几乎总是如此.
如果你的对象有一个非虚拟的析构函数,然后被子类化以添加需要释放的子元素...那么在对象基类上调用析构函数将不会释放子元素.这就是为什么你应该总是声明析构函数是虚拟的.
我们有一个有趣的案例,其中两个共享库引用了一个对象.我们更改了定义以添加需要释放的子对象.我们重新编译了第一个包含对象定义的共享库.
但是,第二个共享库没有重新编译.这意味着它不知道新添加的虚拟对象定义.从第二个共享库中调用的Delete简称为free,并且没有调用虚拟析构函数链.结果是令人讨厌的内存泄漏.
是的,析构函数,即使被明确调用,也会正确地破坏它的子对象.
正如您似乎意识到的那样,这是一种罕见的行为,但也许作为经过良好测试和记录的库的一部分,它可能是有用的.但是文档(和配置文件)它虽然它是有效和安全的,但每个维护者(包括你)都不会对它感到满意.
是的,它将调用所有子析构函数,以便它可以按预期工作.
析构函数毕竟只是一个函数,只是在删除对象时调用它.
因此,如果您使用此方法,请注意以下事项:
#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
Run Code Online (Sandbox Code Playgroud)
实际上在对象上调用delete时,第二次调用析构函数,因此如果在析构函数中删除指针,请确保将它们设置为0,以便第二个调用析构函数时不会发生任何事情(因为删除null)指针什么都不做).