c ++全局变量的初始化顺序

时间:2010-08-18 17:45:50

标签: c++ initialization g++ portability global

这是可移植的还是至少可以安全地使用g ++?

#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 :-)
}

(顺便说一句,我应该发布一个新问题而不是编辑吗?)

3 个答案:

答案 0 :(得分:4)

翻译单元中的全局(通常对应于.c文件)按顺序初始化,因此这是安全的。你只会遇到问题,你是否在彼此依赖的不同目标文件中有全局变量。

这在§3.6.2/ 2

中的标准中指定
  

在单个翻译单元中定义的有序初始化变量应按照翻译单元中的定义顺序进行初始化。

全局变量已经订购了初始化,只要它们未被声明为static

答案 1 :(得分:2)

订单保证是。

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

答案 2 :(得分:0)

对于您更新的问题,我没有通过标准来了解何时应该初始化隐式实例化模板的成员,但显式实例化似乎确实是解决方案:< / p>

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

14.7.2 / 7的标准:

  

类的显式实例化   模板专业化意味着   实例化其所有成员   以前没有明确专门化   在包含的翻译单元中   显式实例化。