手动调用析构函数

高拉夫·巴拉德瓦(Gaurav Bharadwaj)
#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();被忽略,则超出范围时,将调用动态分配的对象的析构函数,并将释放内存tt.reset();使您可以控制何时删除基础对象。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章