模板静态成员初始化顺序

Template static members initialization order

本文关键字:顺序 初始化 静态成员      更新时间:2023-10-16

我有一个问题,有关以前的问题张贴在这里静态字段初始化顺序假设我有以下结构体,有两个静态成员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

我在main()之上初始化了xy,你可以看到y依赖于x,所以最好先初始化x

我的问题:

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

谢谢!

这段代码是安全的,因为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)。