繁体   English   中英

为什么销毁顺序和构造顺序一样,都是static object (C++)?

[英]Why is the order of destruction same as order of construction, with static object (C++)?

代码是:

#include <iostream>
using namespace std;

class A
{
public:
    A() { cout << "A::A" << endl; }
    ~A() { cout << "A::~" << endl; }
};

class B
{
public:
    B() { cout << "B::B" << endl; }
    ~B() { cout << "B::~" << endl; }
};

int main()
{
    B b;
    static A a;
    return 0;
}

output 是:

B::B
A::A
B::~
A::~

非静态object b的scope和static object a的scope在main() function的最后结束。

问题:为什么构造函数的顺序与析构函数的顺序相同?

Static 局部变量将在程序退出时销毁。

块作用域 static 变量的析构函数在程序退出时调用,但前提是初始化成功。

所以b将在main()结束时首先被销毁, a将在这之后被销毁。

对于初始化,

在控件第一次通过它们的声明时被初始化

所以b将首先在main()中初始化,然后a被初始化。

因为它们的寿命不同。 A被声明为函数局部变量 static。

Object 由自动函数局部变量的声明创建,其生命周期在使用该 object 之前开始,并以包含该声明的最嵌套代码块(大括号块)结束。 在您的情况下,这是 function main()主体。

由 static 函数局部变量声明创建的 Object 在执行流进入包含该声明的最嵌套代码块之后并且在使用该 object 之前开始存在。它获得了进程范围的生命周期(停止存在于std::atexit() ),这发生在 function main()将退出之后。

因此,在这种特殊情况下,它们是按声明顺序创建的,但A稍后会被销毁。 如果您的 function 被调用两次,您会看到B将被创建两次,但A只会被创建一次。 如果函数的流程以某种方式省略声明,通过if()语句或通过提前返回,它们的创建顺序将改变或两者都可以省略。

它是特定于实现的细节,但通常通过调用位于std::atexit实现下的库 function,添加与指针值绑定的析构函数的地址,以与全局对象的破坏相同的方式实现函数局部静态的破坏object 本身,但执行可能与用户调用std::atexit的结果并发(或可能不是)。

作为对现有答案的补充,让我们采用更现象学的方法。 考虑对您的示例进行一些小改动:

void foo() {
    B b;
    static A a;
}

int main() {
    foo();
    foo();
}

我假设你知道a只被初始化一次,在第二次调用时我们得到完全相同的 object a ,因为它被声明为static 因此,它不能在第一次调用foo期间或之后立即销毁。 output 的预期第一部分是

B::B    // first call to foo()
A::A
B::~
B::B    // second call to foo()
        // no second call to A::A !
B::~    

a只能在你的程序终止时被销毁,否则你不能在再次调用 function 时“重用”它(这就是为什么我必须修改示例,你不能调用main )。 正如其他答案所详细解释的那样,这发生在main返回之后。 因此 output 的最后一行将是

 A::~

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM