【问题标题】:C++11: std ref global variable and non-function-local thread_local initialization order?C ++ 11:std ref全局变量和非函数局部thread_local初始化顺序?
【发布时间】:2012-10-28 16:08:28
【问题描述】:

在 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 标准是否规定了它们的初始化顺序,或者如果使用未初始化的变量应该产生错误?

对于非函数本地线程_local也是如此:

// global scope

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

thread_local A a;
thread_local B b;

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

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

【问题讨论】:

  • 也许您可以重命名第二个示例中的变量,以便更清楚地了解答案所指的内容。

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


【解决方案1】:

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

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

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

3.6.2/2 涵盖了所有这些。

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 在第一种情况下,如果 b 被动态初始化,则行为不一定是未定义的 - b 将在 a 的构造函数运行之前被初始化为零。这种行为不太可能有帮助,但这是一个单独的问题。
    猜你喜欢
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 2016-11-02
    • 2019-01-19
    • 1970-01-01
    相关资源
    最近更新 更多