#include <iostream>
using namespace std;
namespace GB
{
class Test
{
public:
Test() { cout << "Constructor is executed\n"; }
~Test() {
cout << i << " " << "Destructor is executed\n";
this->i = 7;
}
int i = -1;
};
}
int main()
{
// Test(); // Explicit call to constructor
GB::Test t; // local object
t.i = 6;
t.~Test(); // Explicit call to destructor
return 0;
}
输出量
Constructor is executed
6 Destructor is executed
6 Destructor is executed
我的问题是:
1)为什么析构函数被调用两次。
2)在第一次调用中,析构函数成员值从6更改为7,在第二次调用中,其值变为6。3
)我们可以停止对析构函数的第二次调用(我只想手动保留析构函数的调用)。
为什么析构函数被调用两次。
第一个电话来自线路i.~Test();
。
当变量i
超出范围时(从返回之前main
),第二次调用是对析构函数的自动调用。
在第一次调用中,析构函数成员值从6更改为7,而在第二次调用中,其值为6。
这是由于未定义的行为引起的。当对象的析构函数被调用两次时,您应该期待未定义的行为。当程序进入未定义的行为区域时,请不要试图使其具有逻辑意义。
我们可以停止对析构函数的第二次调用吗(我只想手动保留析构函数的调用)。
当变量超出范围时,您不能禁用对自动变量的析构函数的调用。
如果要控制何时调用析构函数,请使用动态内存(通过调用new Test
)创建对象,并通过调用销毁对象delete
。
GB::Test* t = new GB::Test(); // Calls the constructor
t->i = 6;
delete t; // Calls the destructor
即使在这种情况下,显式调用析构函数几乎总是错误的。
t->~Test(); // Almost always wrong. Don't do it.
请注意,如果要使用动态内存创建对象,最好使用智能指针。例如
auto t = std::make_unique<GB::Test>(); // Calls the constructor
t->i = 6;
t.reset(); // Calls the destructor
如果t.reset();
被忽略,则超出范围时,将调用动态分配的对象的析构函数,并将释放内存t
。t.reset();
使您可以控制何时删除基础对象。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句