变量在析构函数调用中不增加?

时间:2018-08-03 09:59:48

标签: c++

#include <iostream>

using namespace std;

class constructor {
public:
    static int c, d;

    constructor() {
        c++;
    }
    ~constructor() {
        d++;
    }
};

int constructor::c, constructor::d;

int main() {
    constructor c;
    cout<<constructor::c<<" "<<constructor::d;
    return 0;
}

Output: 1 0

如果我显式调用析构函数,则输出为1 1

我想知道,为什么隐式调用析构函数时d不增加?

4 个答案:

答案 0 :(得分:3)

您要在调用c的析构函数之前进行打印-它将在范围的末尾被调用。添加一个新块会产生预期的输出:

int main() {
    {
        constructor c;
    }
    cout<<constructor::c<<" "<<constructor::d;
}

答案 1 :(得分:1)

  

我想知道,为什么隐式调用析构函数时d不增加?

是的,但是到您输出constructor::d时,它尚未被调用。将代码更改为

{
    constructor c;
}
cout<<constructor::c<<" "<<constructor::d;

要查看析构函数调用:此代码在较小范围内构造c,并在较小范围的末尾(这里:在}处)对其进行分解。

答案 2 :(得分:1)

当您尝试打印c成员时,变量d的生命期尚未结束。该变量仍然有效并且在范围内。

如果您尝试例如

int main()
{
    // Add a new nested scope
    {
        constructor c;  // Construct object in nested scope
    }
    // Nested scope ended, so the life-time of c have ended and it has been destructed

    cout<<constructor::c<<" "<<constructor::d;
}

然后应该增加析构函数计数器。

答案 3 :(得分:1)

在您的示例中未调用析构函数,因为该对象在当前作用域中仍然可用。在当前作用域中销毁对象有多种方法,下面是一个快速列表:

创建一个区块

该对象将在块的结尾处被破坏。

{
    constructor c;
}
cout << constructor::c << " " << constructor::d;

重置唯一指针

我们可以创建一个唯一的指针,然后调用reset()方法来释放它。

auto uniquePtr = std::make_unique<constructor>();
uniquePtr.reset();
cout << constructor::c << " " << constructor::d;

重置共享指针

我们还可以创建一个共享指针并reset()

auto sharedPtr = std::make_shared<constructor>();
sharedPtr.reset();
cout << constructor::c << " " << constructor::d;

直接调用析构函数

在可能性列表中,C ++允许您直接调用析构函数。

constructor c;
c.~constructor();
cout << constructor::c << " " << constructor::d;