2012-01-09 37 views
33

我對C++的瞭解是,不應該假定全局實例的構造(和破壞)的順序。std :: cout保證被初始化?

雖然我用全局實例編寫代碼,但在構造函數&析構函數中使用std::cout,我得到了一個問題。

std::cout也是iostream的全局實例。 std::cout保證在任何其他全局實例之前被初始化?

我寫了一個簡單的測試代碼,它完美的工作,但我仍然不知道爲什麼。

#include <iostream> 

struct test 
{ 
    test() { std::cout << "test::ctor" << std::endl; } 
    ~test() { std::cout << "test::dtor" << std::endl; } 
}; 

test t; 

int main() 
{ 
    std::cout << "Hello world" << std::endl; 
    return 0; 
} 

它打印

test::ctor 
Hello world 
test::dtor 

是否有可能按預期的代碼不能運行?

+1

關聯 http://stackoverflow.com/questions/6919593/is-cout-guaranteed-available-during-static-deinitialization這也包括在答案的建設。 – adl 2012-01-09 07:11:12

+0

無法假定靜態存儲持續時間對象在全局作用域的初始化順序,但有強制初始化順序的技巧。 – 2012-01-09 10:04:28

+0

PS。還要注意破壞的順序是有保證的(與構造相反)。 – 2012-01-09 10:11:59

回答

36

答案因使用C++ 03或C++ 11而異。

在C++ 11中,你的代碼是有保證的,但在C++ 03中沒有指定;您唯一的擔保是,在輸入main()時,標準流已經初始化。 (這就是說,所有的主流實現之前對它們進行初始化運行任何動態初始化,使他們蠻好用的。)

您可以通過構建std::ios_base::Init對象強制初始化,就像這樣:現在

#include <iostream> 

struct test 
{ 
    test() { std::cout << "test::ctor" << std::endl; } 
    ~test() { std::cout << "test::dtor" << std::endl; } 

private: 
    std::ios_base::Init mInitializer; 
}; 

test t; 

int main() 
{ 
    std::cout << "Hello world" << std::endl; 
    return 0; 
} 

test它初始化mInitializer並保證流可以使用。

C++ 11通過充當#include <iostream>的每個實例後跟static std::ios_base::Init __unspecified_name__;來解決這個稍微令人討厭的行爲。這自動保證了流可以使用。

+2

在C++ 03中,明顯的意圖(如腳註所示)是爲了確保std :: cin/std :: cout對象在其他對象之前完全構造。 – 2012-01-09 10:08:08

10

根據§27.3/ 2

目的[給std :: cin,標準::法院等]構造,並且 關聯是在一些前或時間建立在第一個 時間內,構造了類ios_base :: Init的對象,並且在主體的主體開始執行之前,在任何情況下均爲 。

+1

對於其他靜態對象相對於std :: cout構造的順序沒有任何說明。 – 2012-01-09 07:06:16

+10

@BasileStarynkevitch:真正的排序,但腳註265(從第27.3/2節引用)表示它應該工作:「靜態對象的構造函數和析構函數可以訪問這些對象以從stdin讀取輸入或將輸出寫入標準輸出或標準錯誤。這可能不是規範性的,但至少明確說明他的代碼應該工作的意圖。 – 2012-01-09 07:09:30

+3

@BasileStarynkevitch:它確實如此。該段繼續說道:「在翻譯單元中包含的結果應該如同定義了具有靜態存儲持續時間的ios_base :: Init的實例。」由於同一翻譯單元中的靜態非局部變量按照聲明的順序進行初始化,所以'cout'保證在其他非局部靜態變量之前被初始化。 (假設你在#include '之前聲明你的變量,我真心希望) – knatten 2013-05-12 16:30:06

2

你的問題是關於構造靜態對象的順序。我相信語言規範使其不確定。

GCC有init_priority屬性可以與訂單一起玩。

我相信你不應該在實踐中擔心太多。