init_seg是C++的一條預處理pragma命令,用於C++全局變數與靜態變數的初始化的定製。
C++程式中,全局變數、靜態變數的初始化分兩種。一種是靜態初始化(static initialization),即用常量值來初始化,在程式被裝入(load)的時候就完成了。另一種是動態初始化(dynamic initialization),簡單地說就是需要調用一個函式來執行初始化,在C運行時刻庫(CRT)的啟動代碼中完成這個工作,即在調用main或者WinMain函式之前已經完成全局變數或靜態變數的初始化。本文討論動態初始化。
基本介紹
- 中文名:init_seg
- 用於:C++全局變數與靜態變數
- 按照:出現順序依次執行
- 定製:不同編譯單元的全局變數
簡介,案例,
簡介
處於同一編譯單元(translate unit)中的全局變數、靜態變數的動態初始化是按照出現順序依次執行,程式結束時銷毀全局變數、靜態變數是按照其初始化順序逆序執行,即後進先出(First-In-Last-Out)。但是,處於不同編譯單元的全局變數、靜態變數的動態初始化是按照什麼順序執行?一般說來,這是不能確定的,因此編寫程式時一般不應該依賴跨編譯單元的初始化順序。
但是,有些情況下確實需要明確不同編譯單元的全局變數、靜態變數的初始化先後順序。
案例
例如,在一個類的構造函式(ctor)中通過流輸出來顯示一些文本信息:
ClassA::ClassA(){
cout<<"ClassA is constructing!"<<endl;
}
這就要求全局對象std::cout在用戶的類初始化之前就已經可以工作了。
Visual C++、Intel C++等編譯器為此提供了一套機制,使得編程者可以定製不同編譯單元的全局變數、靜態變數的初始化順序。把全局變數、靜態變數分為三組,分別稱作compiler組、lib組、user組,初始化順序依次由先至後。而程式結束時的全局變數、靜態變數的銷毀順序為初始化順序的逆序,即user組為先,lib組居中,compiler組最後。源程式中,使用預處理時的pragma命令(proprecossor Pragma Directives)來指定全局變數初始化的分組:
#pragma init_seg(compiler)
#pragma init_seg(lib)
#pragma init_seg(user)
每個編譯單元最多只能有一條pragma init_seg語句,必須放在函式或類的聲明、定義作用域以外,從該條pragma init_seg語句到編譯單元結束範圍內的全部的全局變數、靜態變數都被編譯器處理為具有相應的初始化分組。compiler組一般是C運行時刻庫(C run-time library)使用,如流處理、偽隨機數等等;lib組一般是第三方類庫使用;user組供程式開發者使用。
編譯與連結時的預設行為是:
(1) 指向全局變數初始化代碼的函式指針被放到二進制檔案(obj或exe)的.CRT$XCU節中;
(2) 連結器會合併所有相同名字的節。當section名字中含有$符號時,連結器把$之前的名字做為最終的節名,$之後的字元串的字典順序將作為相同名字的節合併時配列先後的依據;