2010-08-18 98 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

订单保证是。

安全:可疑。取决于你的安全意味着什么。
但正如所写,它是可移植的,不会在我知道的任何编译器上崩溃。