【问题标题】:Template static members initialization order模板静态成员初始化顺序
【发布时间】:2014-05-24 03:26:08
【问题描述】:

我有一个与之前发布的问题相关的问题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

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

我的问题:

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

谢谢!

【问题讨论】:

  • 我删除了我的答案,您可能需要更多标准知识的人,对不起!
  • @user657267 没问题,其实我对答案非常好奇,因为我在任何地方都找不到满意的答案。

标签: c++ templates static static-members


【解决方案1】:

这段代码是安全的,因为Foo&lt;double&gt;::x 有常量初始化,而Foo&lt;double&gt;::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&lt;double&gt;::y 最终可能是 2.20.0(假设在动态初始化期间没有其他任何东西修改 tmp)。

【讨论】:

  • 好的,非常感谢您澄清这部分,+1。但是,template &lt;typename T&gt; T Foo&lt;T&gt;::x = 1.1f; 行是如何工作的呢?声明时不知道类型,静态成员是否默认由float初始化,不管T?还是真的只有在Foo&lt;double&gt; foo;之后才初始化?这是最让我困惑的部分。
  • 当编译器看到Foo&lt;double&gt; 时,它只实例化类以确定所有类成员的名称和类型。然后Foo&lt;double&gt; foo; 使用默认构造函数,因此Foo&lt;double&gt;::Foo() 的函数定义被实例化。该定义使用成员xy,因此Foo&lt;double&gt;::xFoo&lt;double&gt;::y 的成员定义被实例化。编译器使用初始值和/或代码为它们设置永久对象以进行初始化。初始化实际上发生在程序执行时。
  • 好的,现在很有意义!谢谢!
  • 我不认为这是正确的:同一个 TU 中的全局变量按照它们定义的顺序进行初始化。上面代码中保证初始化顺序为tmp,x,y,因此保证y为2.2。
  • @NirFriedman 对于非模板,是的。但是[basic.start.dynamic]/1“如果变量是隐式或显式实例化的特化,则具有静态存储持续时间的非局部变量的动态初始化是无序的......”这最终意味着初始化的顺序是不确定的(如果涉及线程,甚至可能是无序的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-02
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多