我有一个与之前发布的问题相关的问题Static field initialization order
假设我有以下结构,有2个静态成员x
和y
(模板化类型本身)
#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
我将x
和y
初始化为main()
以上,您可以看到y
取决于x
,因此最好是x
首先初始化。
我的问题:
x
和y
的类型仍然未知,那么它们何时真正初始化?在Foo<double> foo;
?main()
之后,静态成员是否实际初始化了
x
和y
的声明顺序似乎无关紧要,即我可以先声明y
然后x
(两者都在结构和在静态初始化中)仍然得到正确的输出,即编译器知道y
依赖于x
。这是一个定义明确的行为(即符合标准)吗?我在OS X上使用g ++ 4.8和clang ++。谢谢!
答案 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.2
或0.0
(假设在动态初始化期间没有其他任何内容修改tmp
)。