手动调用析构函数

gau*_*waj 2 c++ destructor

#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; 
}
Run Code Online (Sandbox Code Playgroud)

输出

Constructor is executed
6 Destructor is executed
6 Destructor is executed
Run Code Online (Sandbox Code Playgroud)

我的问题是:
1)为什么析构函数被调用两次。
2)在析构函数的第一次调用中,成员值从 6 更改为 7 ,在第二次调用中仍然是 6 。
3)我们可以停止析构函数的第二次调用吗(我只想保留手动调用析构函数)。

R S*_*ahu 6

为什么析构函数被调用两次。

第一个电话来自线路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
Run Code Online (Sandbox Code Playgroud)

即使在这种情况下,显式调用析构函数也几乎总是错误的。

t->~Test();  // Almost always wrong. Don't do it.
Run Code Online (Sandbox Code Playgroud)

请注意,如果您想使用动态内存创建对象,最好使用智能指针。例如

auto t = std::make_unique<GB::Test>();  // Calls the constructor
t->i = 6;
t.reset();                              // Calls the destructor
Run Code Online (Sandbox Code Playgroud)

如果t.reset();被忽略,动态分配的对象的析构函数将被调用,并且当t超出范围时内存将被释放。t.reset();允许您控制底层对象何时被删除。