2014-11-06 52 views
3

我知道在不同的翻譯單元(例如不同的cpp/lib/dll/so文件)中定義的靜態變量初始化的順序是未定義的。這是否意味着下面的程序行爲沒有很好的定義?全局對象本質上是不安全的?

#include <vector> 

std::vector<int> v; 

int main() 
{ 
    v.push_back(1); 
} 

編輯:在這裏我用STL向量作爲例子。但它可能是任何其他「第三方」課程的對象。因此,我們不知道該對象是否通過其他全局變量初始化。這意味着在C++中使用非平凡的構造函數創建一個單一的全局對象是不安全的。對?

+0

如果你的全局變量的建設不依賴於任何其他的全局變量,它是安全的。 – 2014-11-06 13:46:44

+0

不,訂單*未指定*,這意味着您不能依賴它們以任何特定順序進行初始化。如果您編寫依賴訂單的代碼,您可能(或不可能)導致未定義的行爲。請注意*指定*翻譯單位(如yours,*)內的訂單*。 – molbdnilo 2014-11-06 13:58:27

+0

我將_undefined_更改爲_not well defined_ – 2014-11-06 14:01:16

回答

8

不,因爲當你在main中使用v時,它是完美定義的。靜態初始化階段發生在你主要使用v前...

的問題出現,如果你使用的不同轉換單元2個全局和存在兩者之間的相關性。有關說明,請參閱C++ FAQ lite。 FAQ中的下一個項目解釋瞭如何避免'慘敗'。

靜態初始化的問題使得C++中的全局變差比任何其他語言都差。好的庫作者知道這個問題,並避免靜態訂單初始化失敗。即使沒有,如果圖書館很好地傳播,有人會遇到這個問題,我希望能夠解決這個問題。但是,第三方庫並非總是寫得很好,他們可以通過一個無知的新寫在你的公司的C++程序員的圖書館...

所以,是的,它是不安全的,你說得對。而在C++中,避免使用全局變量甚至超過其他語言!

注意:Columbo指出,標準並沒有確切地說v是在進入main之前定義的(請參閱他的回答)。你的實例沒有實際的區別。

+0

如果矢量實現使用自己的全局變量呢?那麼有可能v在該變量之後被初始化。 – 2014-11-06 13:47:18

+1

@quantum:那麼,爲什麼一個人不應該使用全局變量:)我認爲庫設計師(好,那是)不使用全局變量。無論如何,如果向量使用全局然後是,靜態初始化順序失敗可能發生... – neuro 2014-11-06 13:52:12

+0

C++標準庫使用全局變量,例如cout和cin。 – 2014-11-06 13:53:48

0

由於只有一個被定義全局對象,只能有一個初始化的排序,因此不存在問題。

6

它在[basic.start.init/4指定:

它是實現定義一個 非局部變量具有靜態存儲持續時間的動態初始化是否在 第一個語句之前完成的主要。如果初始化的主要的第一條語句後推遲到一些 時間點,應當 之前發生在 同一轉換單元定義爲要被初始化的變量的任何函數或變量的第一ODR使用(3.2)。

因此規定v在其首次用於該翻譯單元的任何功能(包括main)之前被初始化。這意味着,在這個特定的程序vmain的第一條語句之前進行初始化。

static initialization order fiasco發生在變量不同翻譯單元依賴於它們的相對次序初始化;根據初始化的不同,初始化可能會相對於對方進行不確定的排序。