2016-09-08 74 views
4

使用靜態數據成員作爲默認參數值時,我需要擔心static initialization order fiasco嗎?例如:作爲C++默認參數,靜態數據成員是否安全?

class Thing { 

    static double const default_blarg; // initialized in another file 

    void run(double blarg=default_blarg); 

}; 

我知道default_blarg將在鏈接時間多數爲不特定點進行初始化,但我不知道什麼時候默認參數run被初始化。如果它在某個時候可能在default_blarg被初始化之前,我可以使用什麼方法來安全地將默認值作爲類接口的一部分公開,而不重複它?將使用constexpr爲靜態數據成員使它安全嗎?

請注意,如果default_blarg不是const(這就是它的原因),我知道這可能會產生一些非常混亂的行爲,而且我沒有試圖使用非靜態數據成員。

回答

4

你仍然必須擔心靜態初始化順序失敗。可以說你有a.cpp和b.cpp。在a.cpp你有

double const Thing::default_blarg = 0; 

現在a.cpp這一點後,run任何調用將有一個初始化的默認,你是好去。不幸的是,在b.cpp中,您有另一個靜態對象,它恰好創建了一個Thing的實例,並調用run

現在我們不知道會發生什麼。如果b.cpp先運行,則default_blarg未初始化,我們有未定義的行爲。

現在你第二部分

,但我不知道何時運行默認參數初始化

函數的默認參數每個函數被調用的時間進行評估。所以只要在default_blarg被初始化之後調用該函數(並且如上所述,它可能不會),那麼你就沒事了。

2

從C++ 11標準,第8.3.6節/ 9:每個函數被調用時

默認參數進行評估。

只要Thing::default_blarg在調用Thing::run之前被初始化,您應該看到可預測的行爲。