我正在调用析构函数来释放内存,但它并没有删除我的对象.它背后的原因是什么?
我的代码是这样的:
class A
{
public:
int a;
A()
{
cout << "a" << endl;
}
};
class B :public A
{
public:
int b;
B()
{
cout << "b" << endl; a = 10; b = 20;
}
~B()
{
cout << a << b << endl;
}
};
Run Code Online (Sandbox Code Playgroud)
我正在使用它:
int main()
{
{
B b;
b.~B();
b.b=100; // why this step is executed?
}
int x;
cin>>x;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
AnT*_*AnT 19
我调用析构函数来释放内存
为什么?析构函数不释放对象占用的内存.从不做.
非平凡的析构函数会终止对象的生命周期,但它不会终止对象的存储持续时间.这意味着内存仍然被分配,它只是变得"原始"(未初始化).所以,从这个意义上讲,它正在摧毁你的对象.
同时,一个简单的析构函数根本没有效果.即使你明确地调用它,对象的生命周期也不会结束.
在你的情况下,析构函数B::~B是非平凡的,这正式意味着通过调用它来结束对象的生命周期.你破坏了它,因为可以销毁一个本地对象.但记忆仍然存在.尝试将该内存作为B对象访问只会导致未定义的行为.
实际上,没有办法手动释放本地对象占用的内存.本地内存始终自动释放.
你没有像这样调用析构函数(嗯,你可以,但通常不会这样做).
对于像你这样的自动变量b,当变量超出范围时,将在某个时刻调用析构函数.您不需要显式调用析构函数.
对于在堆上分配的对象new,将在您之后调用析构函数delete.在这种情况下,您也不会显式调用析构函数.
C++ 03指出12.4 Destructors:
隐式调用析构函数:
- 对于在程序终止时具有静态存储持续时间(3.7.1)的构造对象;
- 对于具有自动存储持续时间(3.7.2)的构造对象,当创建对象的块退出时;
- 当临时对象的生命周期结束时构造的临时对象;
- 对于由new-expression分配的构造对象,通过使用delete-expression;
- 在几种情况下由于处理异常.
也可以显式调用析构函数.
注意:很少需要显式调用析构函数.此类调用的一个用途是使用带有placement选项的new-expression放置在特定地址的对象.为了处理专用硬件资源和编写存储器管理设施,可能需要使用显式放置和销毁对象.
你特别不做你想要做的事情,因为析构函数将被调用两次,一次是由你明确调用,一次是在b超出范围时隐式调用.从标准的同一部分:
一旦为对象调用析构函数,该对象就不再存在; 如果为生命周期结束的对象调用析构函数,则行为未定义.示例:如果显式调用自动对象的析构函数,并且随后以通常调用对象的隐式销毁的方式保留块,则行为未定义.
这篇文章在我最近的C++ 11草案(n3225,2010年11月)中保持不变,并且它在2011年8月的批准之间不太可能发生变化.
你所做的实际上是调用未定义的行为......仅仅因为你调用了析构函数,并不意味着内存被清零或必然“回收”并且无法访问(特别是在分配了自动变量的情况下)在堆栈上而不是堆上)。可能是这样,但这取决于实现,并且通常由于性能原因而不会这样做,这通常是首先使用 C++ 的原因。因此,理论上您可以在调用析构函数后访问对象占用的内存地址处的值...但同样,这是未定义的行为,您可能会遇到从分段错误到损坏内存的无声错误的几乎所有情况其他地方等等