2011-12-08 71 views
16

實施例:C++靜態初始化VS __attribute __((構造))

struct Foo { Foo() { printf("foo\n"); } }; 
static Foo foo; 

__attribute__((constructor)) static void _bar() { printf("bar\n"); } 

它是確定性的閹羊foobar是第一印刷?

(我希望和期望靜態對象的構造函數總是執行有關構造屬性不說什麼第一,但不知道和GCC的文檔)。

+0

你在哪裏使用這種編譯器功能? – AlexTheo

+0

@AlexTheo:這很常見。見例如。每次你想要初始化某些東西時,你通常都會使用它。 – Albert

+0

其實我更喜歡像靜態常量布爾_isInitialized 並且與我初始化我的物體,像常量布爾MyClass的一個私有的初始化函數:: _ =將IsInitialized initFunction(); 但是,這些僅適用於我喜歡首先初始化的對象。否則構造函數應該做一個工作。 – AlexTheo

回答

13

foo將首先打印,作爲對象按其聲明的順序進行初始化。運行看:

順便說一句,__attribute__((constructor))不是標準C++。這是GCC的延伸。所以你的程序的行爲取決於GCC如何定義它。簡而言之,它是實現定義的,根據它foo首先被打印。

doc的說,

構造屬性導致函數被自動調用之前執行進入主()。同樣,析構函數的屬性也會導致函數在main()完成或exit()被調用後自動調用。具有這些屬性的函數對於初始化將在程序執行過程中隱式使用的數據非常有用。

您可以提供一個可選的整數優先級來控制構造函數和析構函數的運行順序。具有較小優先級編號的構造函數在具有較大優先級編號的構造函數之前運行;相反的關係適用於析構函數。所以,如果你有一個分配資源的析構函數和一個釋放相同資源的析構函數,那麼這兩個函數通常具有相同的優先級。 構造函數和析構函數的優先級與爲命名空間範圍C++對象(請參閱C++屬性)指定的優先級相同。

我想以粗體文字所暗示的,對象在其聲明的順序進行初始化,正如我以前說過,這是相當多的online demo證實也。

我猜你也想閱讀:

如果你想控制/改變初始化順序,您可以使用init_priority屬性,提供優先。從the page摘自:

Some_Class A __attribute__ ((init_priority (2000))); 
Some_Class B __attribute__ ((init_priority (543))); 

這裏,BA之前進行初始化。

+0

恩,所有評論被刪除了?這怎麼可能。所以,這裏是我的評論:對我來說有趣的是這個信息和最後一個鏈接,特別是。這樣的:*在標準C++,在名字空間域中定義的對象,保證在嚴格按照它們在一個給定的翻譯單元定義的順序進行初始化* – Albert

+0

事實上,我只是測試它在另一示例中,並且它不」。似乎是那裏的情況。 – Albert

+0

@Albert:發佈代碼。實際的代碼,沒有改變它一點。還張貼你得到的輸出。 – Nawaz

1

看起來不確定。在使用GCC編譯時,我的問題中也有foo\nbar\n作爲示例的輸出。但是,使用LLVM/Clang編譯時,我得到了bar\nfoo\n

但是,因爲我不知道這可能是鐺的錯誤,我填一個bug報告here編輯:我在那裏得到了答案,它似乎是一個真正的叮噹中尚未修復的錯誤。不知道從那裏得出什麼結論。預期的和應該的行爲在這裏確實是確定性的,但是,你不能依賴它,因爲至少有一個主要的編譯器(Clang)做錯了(或者不同於GCC,如果我們把它作爲規範__attribute__((constructor)))。

注意,這可能是在現實世界中的代碼真正相關的和重要的。例如。 here是一個種子隨機發生器失敗與鏗鏘的例子。

+0

刪除這篇文章。並編輯你的問題,併發布到那裏。答案應該是答案,而不是問題。 – Nawaz

+1

@Nawaz:你是什麼意思?爲什麼?這是一個答案,我的問題是一個問題。如果你不清楚這個答案的答案是否是真正的問題:它基本上說它是不確定的。 – Albert

+0

好的。你怎麼能說它是非確定性的,你怎麼能這樣說:「*因此,看起來rnd的構造函數是在_rand_engine__init *之後執行的。也發佈一些解釋! – Nawaz