[英]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.