2013-02-16 26 views
4

Here你會在下找到以下聲明哪個頭?下面的方案如何保證只有一個對象cin,cout,...的定義?

最後,<iostream>提供了八種標準全局對象(CIN,COUT 等)。爲了正確執行此操作,此標頭還提供<istream><ostream>標頭的 內容,但不提供其他內容。標題的內容 樣子

#include <ostream> 
#include <istream> 

namespace std 
{ 
    extern istream cin; 
    extern ostream cout; 
    .... 

    // this is explained below 
    static ios_base::Init __foo; // not its real name 
} 

現在,前面提到的運行時間延長:之前的任何自己的代碼使用它們的全局對象必須 初始化;這是由標準保證的 。像任何其他全局對象一樣,它們必須是 ,且只能初始化一次。這通常通過 這樣的構造完成,因此,標準中指定的嵌套類ios_base :: Init爲 。

它是如何工作的?由於標題包含在任何 代碼之前,所以__foo對象在任何對象之前構造。 (全局對象按聲明順序構建,並按相反順序銷燬)。構造函數首次運行時,將設置8個流對象。

我的問題:當我包括幾個.cpp文件頭文件<iostream>,請問上述擔保方案會有只是一個定義的對象cincout,等等?

+0

「一個定義」不是很有趣 - 這只是(編譯的)標準庫的一部分。有趣的是「一次初始化」。 (我認爲這種技術被稱爲[「Schwartz計數器」](http://stackoverflow.com/q/9251763/596781)。) – 2013-02-16 10:20:27

+2

AFAIK,'cout','cin'等人。對象只是在頭文件中聲明爲'extern',實際的定義在標準的lib文件中。現在,'ios_base :: Init'被聲明爲'static',因此每個翻譯單元都有自己的副本。 Init'對象的構造函數/析構函數進行某種引用計數,以瞭解何時初始化/銷燬標準流對象。至少這是[stdlibC++似乎這樣做](http://gcc.gnu.org/viewcvs/trunk/libstdc%2B%2B-v3/include/std/iostream?view=markup)。 – jrok 2013-02-16 10:27:58

+0

@jrok你說的一切都很清楚。當''包含在幾個'.cpp'文件中時,我不明白'ios_base :: Init'如何避免全局對象cin,cout,...的多重定義。 – 2013-02-16 10:35:15

回答

3

這並不能保證。一個定義問題可以通過簡單地在作爲庫一部分的.cpp文件中定義流對象來解決。問題中的代碼僅包含標準流的聲明

什麼是保證是對象將初始化之前使用。 C++中的全局對象存在的一個問題是,雖然它們的在每個.cpp文件中按順序初始化,但我們不知道鏈接器將從單獨文件中放置對象的順序。如果一個對象在初始化之前試圖使用另一個對象,這可能會導致問題,我們不知道確切的順序 - 請參閱Static initialization order fiasco

這裏使用的一種解決方法是在聲明流對象的頭文件中放入一個Init對象。因爲在使用流之前必須包含頭部,所以我們知道這個對象將位於文件的頂部,並因此在可能使用流的其他對象之前構建。

現在,Init類的構造函數負責流對象的初始化。這必須儘早完成,而且只能進行一次。具體到每個實現如何,但代碼暗示使用計數器跟蹤創建的對象數量(並且可能大概是首先對待第一個對象)。

這只是一種使用標準語言的方法。某些實現有其他技巧,如#pragmainit_priority指令說服連接器在用戶代碼之前放置庫代碼。在這種情況下,它只是通過魔法工作,而不使用Init類。

+0

'什麼是保證是對象將被使用前被初始化。 C++中全局對象的一個​​問題是,儘管它們在每個.cpp文件中按順序初始化,但我們不知道鏈接器將從單獨文件中放置對象的順序。這可能會導致問題,如果一個對象試圖在另一個對象被初始化之前使用另一個對象,並且我們不知道確切的順序。「據我所知,這個問題已經在C++ 11中解決了,至少根據到這個答案http://stackoverflow.com/a/8785008/1042389。 – 2013-02-16 14:12:23

+0

唯一的區別是在C++ 11中說實現應該像構建一個Init對象那樣工作。這也是它在C++ 03中的工作方式,它只是沒有被拼寫出來(因爲它被認爲是顯而易見的:-)。參見[圖書館缺陷報告#369](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#369) – 2013-02-16 15:14:14

+0

'一個定義問題可以通過簡單地定義流在作爲庫的一部分的.cpp文件中對象一次。「你有任何參考來支持這個嗎?標準是否對此有所說明? – 2013-02-16 15:26:55