C ++ 11:std ref全局变量和非函数本地thread_local初始化顺序?

时间:2012-10-28 16:08:29

标签: c++ c++11 language-lawyer

在静态初始化阶段进入main之前,构造了带有非平凡构造函数的C ++ 11中的全局变量。

同样,在每个线程的“thread_local初始化阶段”中构造非函数本地thread_local变量。

C ++ 11标准是否指定了这些变量的构造顺序?在这两种情况下,如果有两个变量:

// global scope

A::A() { b.f(); }  // A constructor uses global b

A a;
B b;

C ++ 11标准是否指定了它们应该初始化的顺序,或者如果使用未初始化的变量应该产生错误?

同样对于非函数本地thread_local:

// global scope

A::A() { b.f(); }  // A constructor uses global b

thread_local A a;
thread_local B b;

标准是否指定了它们必须构造的顺序,是否定义了在初始化变量之前从另一个构造函数中使用变量会发生什么?

您能否提供 C ++ 11标准参考,以支持您为获得答案而提出的任何声明。

2 个答案:

答案 0 :(得分:2)

您的声明“在静态初始化阶段进入main之前,构造了带有非平凡构造函数的C ++ 11中的全局变量”。似乎并不完全正确 - 它们可能在动态初始化阶段之前不会被初始化

对于具有“有序初始化”的变量,您的第一个a和b是,然后标准说

  

在单个内定义的有序初始化变量   翻译单位应按其顺序初始化   翻译单位中的定义。

3.6.2 / 2涵盖了所有这些。

编辑:据我所知,你的第二个a和b没有订购初始化,并且可以按任意顺序初始化。但我可能会遗漏一些东西。

答案 1 :(得分:2)

对于静态存储期,我同意Alan的回答。如果初始化位于相同的转换单元中,则它们的动态初始化是这些对象定义的顺序。允许编译器初始化b作为静态初始化,如果它可以弄清楚如何(按3.6.2 / 3)。所以第一个程序可能会也可能不会调用未定义的行为,这可能是一个坏主意。

对于动态存储持续时间,请注意3.7.2 / 2:

  

具有线程存储持续时间的变量应在其第一次使用odr(3.2)之前初始化,如果构造,则应在线程退出时销毁。

因此,线程局部变量更像是函数局部静态变量,而不是命名空间范围的静态变量。第二个程序没有未定义的行为。