4

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

同样,非函数局部 thread_local 变量是在每个线程的“thread_local 初始化阶段”期间构造的。

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

// global scope

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

A a;
B b;

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

同样对于非函数本地线程_本地:

// global scope

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

thread_local A a;
thread_local B b;

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

您能否提供一个C++11 标准参考来支持您提出的任何要求以获得答案。

4

2 回答 2

2

对于静态存储持续时间,我同意 Alan 的回答。如果初始化在同一个翻译单元中,它们的动态初始化是那些对象定义的顺序。b如果编译器可以弄清楚如何(根据 3.6.2/3),则允许编译器将其初始化为静态初始化。所以第一个程序可能会或可能不会调用未定义的行为,这可能是一个坏主意。

对于动态存储期限,注释 3.7.2/2:

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

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

于 2012-10-28T17:35:35.630 回答
2

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

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

在单个翻译单元中定义的具有有序初始化的变量应按照它们在翻译单元中的定义顺序进行初始化。

3.6.2/2 涵盖了所有这些。

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

于 2012-10-28T16:24:21.893 回答