2013-01-24 53 views
0

據我所知,在任何人嘗試使用這些對象之前,需要調用全局對象的構造函數。但是在我的程序中,這似乎並不是這樣。這是我的簡化的代碼首次使用對象後調用的全局對象構造函數

#include <iostream> 

using namespace std; 

struct type_data 
{ 
    int id; 

    type_data() 
     : id(-1) // set some invalid id 
    { 
     cout << "creating a new type data" << endl; 
    } 
}; 

template <typename T> 
struct type_data_for_type 
{ 
    static type_data data; 
}; 
template <typename T> 
type_data type_data_for_type<T>::data; 


struct type_registry 
{ 
    static type_registry& instance() 
    { 
     static type_registry i; 
     return i; 
    } 

    void register_type(type_data& t) 
    { 
     cout << "registering a type" << endl; 
     t.id = last_id++; 
    } 

    int last_id; 
}; 

template <typename T> 
struct registrator 
{ 
    registrator() 
    { 
     type_registry::instance(). 
      register_type(type_data_for_type<T>::data); 
    } 

    int unused; 
    static registrator payload; 
}; 
template <typename T> 
registrator<T> registrator<T>::payload; 

class foo {}; 

inline void register_foo() 
{ 
    registrator<foo>::payload.unused = 1; 
} 

int main() 
{ 
    cout << type_registry::instance().last_id << endl; 
    cout << type_data_for_type<foo>::data.id << endl; 
    return 0; 
} 

基本上它經由register_foo全局寄存器的類型FOO(I用gcc版本4.6.3-1ubuntu5編譯它)。我希望可以將輸出爲:

creating a new type data 
registering a type 
1 
0 

但取而代之的則是:

registering a type 
creating a new type data 
1 
-1 

這意味着,我給自己定一個type_data對象的ID它的構造函數被調用之前。

那麼,這是一個編譯器錯誤?我錯過了什麼嗎?我可以做這個工作嗎?

+0

我相信你不能依賴於構造全局對象的相對順序 –

+2

相關:http://www.parashift.com/c++-faq/static-init-order.html [10.14]什麼是「靜態初始化順序悲劇「? – Patashu

回答

4

我相信你不能依賴這種情況下類模板的靜態成員變量的初始化順序。

相關這裏§C++標準的3.6.2/2:

*「非本地變量,靜態存儲持續時間的動態初始化不管是有序還是無序 明確專門的模板類靜態的定義數據成員已經命令初始化。其他類模板靜態數據成員(即隱式或顯式實例化的特化)* 有無序初始化。「

當然也§9.4.2/6,它是指上面的規則:

「靜態數據成員被初始化,並且破壞了完全一樣的非本地變量(3.6.2,3.6.3) 「。

1

發生什麼事是registrator<foo>::payload正在type_data_for_type<foo>::data之前被初始化。但是,registrator<foo>的構造函數使用type_data_for_type<foo>::data

您不能依賴以任何特定順序調用的靜態初始化器,而在您的情況下,它的發生順序與您想要的順序完全相反。

但我認爲潛在的問題是,您的解決方案過於複雜。你真的需要區分type_data_for_typeregistrator嗎?無法註冊類型數據對象?

+0

不幸的是沒有。這是代碼的簡化版本。實際上,我需要能夠訪問模板函數中的類型數據(其中包含比ID更多的類型數據)。 –

+0

訪問模板函數中的類型數據的更習慣的方式是使用特徵。 – Pseudonym

+0

但我不得不手動專門化我的特質結構,而在這種情況下,數據會自動填充。 –

相關問題