2012-02-17 15 views
3

我正在使用需要定義全局數組結構的第三方C++庫供它使用。我不喜歡這種設計,但我堅持下去。對靜態數據使用__declspec(selectany)是否對該數據的初始化順序有任何影響?

LibStruct g_Structs[] = 
{ 
    { /* structure initialization data */ }, 
    { /* structure initialization data */ }, 
     // etc 
}; 
int g_NumStructs = sizeof(g_Structs)/sizeof(g_Structs[0]); 

我想稍微分解一下,以便類可以提供適用於該類的結構定義。這可能會導致靜態初始化失敗,除非使用getter或main()開始之後安全地完成初始化。

如果我將該類的頭文件中的每個類的MyStructs聲明爲具有__declspec(selectany)屬性(特定於Visual C++)的靜態數據成員,那麼它似乎工作。 selectany屬性是否對該數據的構建順序有影響?靜態數據成員的selectany定義在全局數組之前的出現是否意味着它是按照這個順序構造的?或者,這種行爲僅取決於多個selectany定義中的哪一個被鏈接器拋棄? selectany有任何保證嗎?

// In the header for Class1 
static const LibStruct __declspec(selectany) Class1::m_MyStruct = { /* structure initialization data */ }; 

// In the header for Class2 
static const LibStruct __declspec(selectany) Class2::m_MyStruct = { /* structure initialization data */ }; 

// Danger - potential for static initialization fiasco? 
LibStruct g_Structs[] = 
{ 
    Class1::m_MyStruct, 
    Class2::m_MyStruct, 
    // etc 
}; 
int g_NumStructs = sizeof(g_Structs)/sizeof(g_Structs[0]); 

澄清:

在這種情況下MYSTRUCT是C樣式結構不具有構造或虛函數和僅包含指向它們全部初始化爲指向其它全局數據或非成員函數。所以使用= {}語法的全局常量MyStruct的初始化不應該運行任何構造函數代碼。

回答

2

添加我自己的答案,因爲還沒有任何其他答案。

看來這段代碼可以工作,但這只是因爲微軟編譯器實現選擇通過在任何靜態初始化代碼運行之前將可執行映像的.data部分映射到內存中來初始化全局const原始數據。所以它依賴於實現,但依賴於編譯器的靜態初始化策略,而不是使用__declspec(selectany)。

單步執行應用程序的入口點顯示這看起來是正確的。靜態常量MyStruct對象已在入口點初始化,但全局數組稍後將以靜態構造代碼初始化。

相關問題