實施例:C++靜態初始化VS __attribute __((構造))
struct Foo { Foo() { printf("foo\n"); } };
static Foo foo;
__attribute__((constructor)) static void _bar() { printf("bar\n"); }
它是確定性的閹羊foo
或bar
是第一印刷?
(我希望和期望靜態對象的構造函數總是執行有關構造屬性不說什麼第一,但不知道和GCC的文檔)。
實施例:C++靜態初始化VS __attribute __((構造))
struct Foo { Foo() { printf("foo\n"); } };
static Foo foo;
__attribute__((constructor)) static void _bar() { printf("bar\n"); }
它是確定性的閹羊foo
或bar
是第一印刷?
(我希望和期望靜態對象的構造函數總是執行有關構造屬性不說什麼第一,但不知道和GCC的文檔)。
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)));
這裏,B
是A
之前進行初始化。
看起來不確定。在使用GCC編譯時,我的問題中也有foo\nbar\n
作爲示例的輸出。但是,使用LLVM/Clang編譯時,我得到了bar\nfoo\n
。
但是,因爲我不知道這可能是鐺的錯誤,我填一個bug報告here。 編輯:我在那裏得到了答案,它似乎是一個真正的叮噹中尚未修復的錯誤。不知道從那裏得出什麼結論。預期的和應該的行爲在這裏確實是確定性的,但是,你不能依賴它,因爲至少有一個主要的編譯器(Clang)做錯了(或者不同於GCC,如果我們把它作爲規範__attribute__((constructor))
)。
注意,這可能是在現實世界中的代碼真正相關的和重要的。例如。 here是一個種子隨機發生器失敗與鏗鏘的例子。
你在哪裏使用這種編譯器功能? – AlexTheo
@AlexTheo:這很常見。見例如。每次你想要初始化某些東西時,你通常都會使用它。 –
Albert
其實我更喜歡像靜態常量布爾_isInitialized 並且與我初始化我的物體,像常量布爾MyClass的一個私有的初始化函數:: _ =將IsInitialized initFunction(); 但是,這些僅適用於我喜歡首先初始化的對象。否則構造函數應該做一個工作。 – AlexTheo