2012-10-28 35 views
4

具有非平凡構造函數的C++ 11中的全局變量在靜態初始化階段進入main之前構造。C++ 11:std ref全局變量和非函數本地thread_local初始化順序?

同樣,非線程本地thread_local變量是在每個線程「thread_local初始化階段」期間構造的。

C++ 11標準是否規定了構建這些變量的順序?在這兩種情況下,如果有兩個變量:

// global scope 

A::A() { b.f(); } // A constructor uses global b 

A a; 
B b; 

請問C++ 11個標準指定以什麼順序,他們將被初始化,或者,如果一個變量用於初始化應該產生一個錯誤?

同樣,對於非功能本地thread_local:

// global scope 

A::A() { b.f(); } // A constructor uses global b 

thread_local A a; 
thread_local B b; 

是否標準規定必須將它們構建的秩序,它規定如果變量是從另一個構造方法之前,它曾經會發生什麼初始化?

您能否提供C++ 11標準參考號以支持您提出的任何索賠要求。

+0

也許你可以重新命名第二個例子中的變量,使其更清楚地知道答案所指的是什麼。 –

回答

2

您的陳述「在靜態初始化階段,在帶有非平凡構造函數的C++ 11中的全局變量在進入main之前構造」。似乎不完全正確的 - 他們可能不會被初始化,直到動態初始化階段

對於「命令初始化」,變量,你的第一個a和b,那麼標準說

變量在單個 中定義的有序初始化應在翻譯單元中按其 定義的順序進行初始化。

3.6.2/2涵蓋了所有這些。

編輯:據我可以告訴你的第二個a和b沒有有序初始化,並可以按任意順序初始化。但我可能會錯過一些東西。

2

對於靜態存儲期限,我同意Alan的回答。如果初始化在同一個翻譯單元中,它們的動態初始化就是這些對象定義的順序。編譯器可以將初始化爲b作爲靜態初始化,而不是如果它能夠計算出(按照3.6.2/3)。所以第一個程序可能會或可能不會調用未定義的行爲,並且可能是一個壞主意。

對於動態存儲持續時間,請注意3.7.2/2:

與線程存儲持續時間的變量應在其第一ODR使用之前被初始化(3.2),如果構造,應在螺紋破壞出口。

因此,與命名空間範圍的靜態變量相比,線程局部變量更像函數局部靜態變量。第二個程序沒有未定義的行爲。

+1

在第一種情況下,如果b是動態初始化的,則行爲不一定是未定義的 - 在運行構造函數之前,b將被初始化爲零。這種行爲不太可能有幫助,但這是一個單獨的問題。 –