跨編譯單元之初始化次序

所謂static對象,其壽命從被構造出來直到程序結束爲止,因此

stack和heap-based對象都被排除。這種對象包括global對象,定

義於namespace作用域內的對象、在class內、在函數內、以及在

file作用域內被聲明爲static的對象。函數內的static對象稱爲

local static對象(因爲它們對函數而言是local),其他static

對象稱爲non-local static對象。程序結束時static對象會被自動

銷燬,也就是它們的析構函數會在main()結束時被自動調用。

所謂編譯單元(translation unit)是指產出單一目標文件

(single object file)的那些源碼。基本上它是單一源碼文件加

上其所含入的頭文件。

C++對“定義於不同編譯單元內的non-local static對象”的初始

化次序並無明確定義。

問題來了:如果某編譯單元內的某個non-local static對象的初始

化動作使用了另一個編譯單元內的某個non-local static對象,它

所用到的這個對象可能尚未被初始化。

解決方法:
將每個non-local static對象搬到自己的專屬函數內(該對象在此

函數內被聲明爲static)。這些函數返回一個reference指向它所

含的對象。然後用戶調用這些函數,而不直接指涉這些對象。這個

專屬函數我們叫它reference-returning函數。其形式大致爲:

class classNameA
{
...
};
class classNameB
{
...
inline classNameA& clsNameAObj()
{
static classNameA clsNameA;
return clsNameA;
}
...
}

這個方法的基礎在於:C++保證,函數內的local static對象會在

“該函數被調用期間”“首次遇上該對象之定義式”時被初始化。

但從另一個角度看,這些函數“內含static對象”的事實使他們在

多線程系統中帶有不確定性。我們可以在程序的單線程啓動階段手

工調用所有reference-returning函數,這可消除與初始化有關的

“競速形式(race conditions)”。

我們總是需要爲內置型對象進行手工初始化,因爲C++不保證初始化他們。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章