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