模板静态成员初始化顺序

时间:2014-05-24 03:26:08

标签: c++ templates static static-members

我有一个与之前发布的问题相关的问题Static field initialization order 假设我有以下结构,有2个静态成员xy(模板化类型本身)

#include <iostream>

using namespace std;

template <typename T>
struct Foo
{
    static T x;
    static T y;
    Foo()
    { 
         cout << "x = " << x << endl;
         cout << "y = " << y << endl;
    }
};

template <typename T>
T Foo<T>::x = 1.1f;

template <typename T>
T Foo<T>::y = 2.0 * Foo<T>::x;


int main()
{
    Foo<double> foo;
}

输出:

x = 1.1 
y = 2.2

我将xy初始化为main()以上,您可以看到y取决于x,因此最好是x首先初始化。

我的问题:

  1. 在初始化时,xy的类型仍然未知,那么它们何时真正初始化?在Foo<double> foo;
  2. 中的模板实例化main()之后,静态成员是否实际初始化了
  3. 如果是,xy的声明顺序似乎无关紧要,即我可以先声明y然后x(两者都在结构和在静态初始化中)仍然得到正确的输出,即编译器知道y依赖于x。这是一个定义明确的行为(即符合标准)吗?我在OS X上使用g ++ 4.8和clang ++。
  4. 谢谢!

1 个答案:

答案 0 :(得分:3)

此代码是安全的,因为Foo<double>::x具有常量初始化,但Foo<double>::y具有动态初始化。

3.6.2 / 2:

  

执行常量初始化

     
      
  • ...

  •   
  • 如果构造函数调用未初始化具有静态或线程存储持续时间的对象,并且其初始值设定项中出现的每个完整表达式都是常量表达式。

  •   
     

一起,零初始化和常量初始化称为静态初始化;所有其他初始化都是动态初始化。在进行任何动态初始化之前,应执行静态初始化。

另一方面,如果你有:

double tmp = 1.1;

template <typename T>
T Foo<T>::x = tmp;

template <typename T>
T Foo<T>::y = 2.0 * Foo<T>::x;

该代码不“安全” - Foo<double>::y最终可能是2.20.0(假设在动态初始化期间没有其他任何内容修改tmp)。