2010-08-18 96 views
1

這是可移植的還是至少安全的使用g ++?全局變量的C++初始化順序

#include <iostream> 
#include <vector> 

struct c {}; 
std::vector<c*> v; 
struct i : c { i() { v.push_back (this); } } a, b, c; 

int main() { 
    std::cout << v.size() << "\n"; // outputs 3 with g++ 
} 

編輯:

好吧,我需要的原來是有點困難:與模板相同的代碼:

#include <iostream> 
#include <vector> 

template < typename T > struct c {}; 
template < typename T > struct cv { static std::vector<c<T>*> v; }; 
template < typename T > std::vector<c<T>*> cv<T>::v; 
template < typename T > struct i : c<T> { i() { cv<T>::v.push_back (this); } }; 

cv<int> dummy; // even this won't initialize cv<int>::v 
i<int> a, b, d; 

int main() { 
    std::cout << cv<int>::v.size() << "\n"; // outputs 0 :-(
} 

我怎麼能解決這個問題,以按上述方式工作?

編輯2:

這裏是一個醜陋的修復與宏(我希望有一個更好的方式來做到這一點):

#include <iostream> 
#include <vector> 

template < typename T > struct c {}; 
template < typename T > struct cv; 
#define INITCV(X) \ 
    struct v##X { static std::vector<c<X>*> v; }; \ 
    std::vector<c<X>*> v##X::v; \ 
    template <> struct cv<X> { typedef v##X V; } 
template < typename T > struct i : c<T> { i() { cv<T>::V::v.push_back (this); } }; 

INITCV(int); 
i<int> a, b, d; 

int main() { 
    std::cout << cv<int>::V::v.size() << "\n"; // outputs 3 again :-) 
} 

(順便說一句,我應該已經發布了一個新問題而不是編輯?)

回答

0

爲您更新的問題,我沒有通過標準的涉水找出來的時候的隱式實例化的模板成員都應該被初始化,但明確實例化似乎是解決方案:

template class cv<int>; // Not a dummy. Declares the template like a class. 

Standardese在14.7.2/7:

類 模板專業化的顯式實例意味着 實例化其所有成員的以前未明確專用的 在包含 顯式實例的翻譯單元中。

4

翻譯單元中的全局(通常對應於.c文件)按順序初始化,因此這是安全的。你只會遇到問題,你有全局變量在不同的對象文件中相互依賴。

這在標準中指定在§3.6.2/ 2

變量與單個翻譯單元內定義的有序初始化應在其定義在翻譯單元的次序進行初始化。

只要它們沒有聲明爲static,全局變量就會進行初始化。

+0

謝謝你在規範中查找。不幸的是,這似乎並不適用於模板,就像我修改過的問題一樣。 – Thomas 2010-08-18 18:42:17

2

訂單保證是。

安全:可疑。取決於你的安全意味着什麼。
但正如所寫,它是可移植的,不會在我知道的任何編譯器上崩潰。