2011-12-02 41 views
3

考慮一個單一的翻譯單元下面的代碼:靜態數據成員的初始化爲了

class C { 
private: 

    struct Init { 

     Init() { 
      /* compute data once here */ 
     } 
    }; 
    static const Init& i; 
    static int data[]; 
public: 
    /* interface for reading data */ 
}; 

const C::Init& C::i = Init(); 
int C::data[200]; 
  1. 是C ::我後的C ::數據總是被初始化,無論兩者的定義的順序?
  2. 此解決方案是最優雅的一次用於計算靜態數據嗎?
+1

你能詳細解釋一下你認爲答案是針對你提出的問題嗎? – Grammin

+0

1.我認爲是因爲涉及的類型。數據是int [],而我是const Init&,它可能涉及main()之前的一個更精細的構造,但是在其他基本(POD?)類型的靜態數據成員之後。我需要兩種類型對象的標準和正確術語的確認。 – Martin

回答

6

int C::data[200]零初始化,這意味着它是靜態初始化。靜態初始化在動態初始化之前。由於C::Init::Init()不是一個常量表達式,因此C::i被動態初始化,必然C::data

詳情請參閱3.6.2。

私售報價:

變量與靜態存儲時間[...]應爲零初始化任何其他初始化發生之前。 [...]一起,零初始化和常量初始化被稱爲靜態初始化;其他所有初始化都是動態初始化靜態初始化應在任何動態初始化發生之前執行。

+0

好像你這樣的人存在:) +1 – FailedDev

+0

值得注意的是,靜態初始化的順序沒有定義,也不需要它 - 靜態初始化變量的所有初始值在編譯時已經知道,所以順序他們的初始化不能有任何可觀察到的效果。 –

0

C::data在那裏沒有初始化,所以順序無關緊要。

較短的解決方案是使用靜態函數和虛擬變量:

class C { 
private: 

    static void Init() { 
     /* compute data once here */ 
    } 

    static bool data_init_helper; 
    static int data[]; 
public: 
    /* interface for reading data */ 
}; 

bool C::data_init_helper = (C::Init(), false); 
int C::data[200]; 
0

是C ::我後的C ::數據總是被初始化,無論兩者的 定義的順序?

如果訂單在同一編輯 單位中定義,則訂單得到保證,否則保證訂單。

此解決方案是最優雅的一次用於計算靜態數據嗎?

號如果你真的不得不做靜態的,那麼一個更好的方法(和防止可能的靜態初始化順序的悲劇)就是做這樣的:

struct someDataStr 
{ 
    int data[200]; 
}; 
someDataStr& AccessData() 
{ 
    static someDataStr *ptr = NULL; 
    if (NULL == ptr) 
    { 
    ptr = new someDataStr; 
    // initialize value 
    } 
    return *ptr; 
} 

如果它不」必須是靜態的,然後使用依賴注入,並將包含數據的對象傳遞給使用它的所有類。