【问题标题】:Does static initialization order fiasco apply to block-scope static variables?静态初始化顺序惨败是否适用于块范围静态变量?
【发布时间】:2021-02-23 09:17:31
【问题描述】:

这个问题很像主题中的问题,我找不到明确的答案,因为几乎每个示例都涵盖了两个相互依赖的命名空间范围实例。一个例子:

a.hpp

class MyGlobal {/*definition*/};
extern const MyGlobal global;

a.cpp

const MyGlobal global;

b.hpp

void myFunc();

b.cpp

extern const MyGlobal global;
class MyLocalStatic
{
    public:
    MyLocalStatic() { /* do something with global */ }
    
};

void myFunc()
{
    static MyLocalStatic s;
}

main.cpp

int main() { myFunc(); }

假设MyGlobalMyStaticLocal 都有一些非平凡的构造函数,因此在动态初始化期间被初始化。 我知道编译器可以将动态初始化推迟到实际使用的变量。但是,如果它根本不在同一个 TU 中使用呢?编译器什么时候决定初始化它?

另一个问题:如果global 是常量初始化,我认为没有问题。但是s 是否有可能也被常量初始化(并且仍然以某种方式依赖于global)或者这是不可能的?

不胜感激标准中的一些引用:)

【问题讨论】:

  • 函数范围内的静态变量在函数第一次被调用时被初始化。这里不相关,但初始化是线程安全的。你还有一些specifics here
  • @TedLyngmo 谢谢我不知道这个标签,补充说:D
  • @super 我的问题不是MyLocalStatic 何时被初始化,而是“什么保证MyGlobal 在它之前被初始化”(如果有的话)
  • 嗯,它在第一次调用函数时被初始化的事实应该告诉你,全局变量保证在它之前被初始化。因此,即使您没有询问 MyLocalStatic 何时初始化,我的评论仍然可以回答您的问题。
  • @super 标准规定 是否在 main 的第一条语句之前完成具有静态存储持续时间的非局部变量的动态初始化是实现定义的。 。那么标准的哪一部分做出了您所说的保证?

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


【解决方案1】:

Function-local static 变量在控件第一次到达其声明时创建。在您的情况下,它会在输入main 后发生,此时global 肯定会被初始化。

s 是否也有可能被常量初始化

是的。

...仍然以某种方式依赖于global

是的,仅当 globalconstexpr 时。

如果变量是常量初始化的,则无需担心。在编译时没有静态初始化顺序失败。

【讨论】:

  • 仅作为旁注:独立于静态初始化顺序惨败,仍然有很小的机会搞砸事情:外部链接情况下跨多个翻译单元的常量变量的多个不同定义( UB)。
  • @HolyBlackCat 好吧,您看到标准似乎不同意“global 肯定已初始化”(或者我读错了?):这是实现定义的具有静态存储持续时间的非局部变量的动态初始化在main 的第一条语句之前完成。如果初始化被推迟到main 的第一条语句之后的某个时间点,它应该发生在与要初始化的变量在同一翻译单元中定义的任何函数或变量的第一次 odr-use (3.2) 之前。
  • 这种情况下的 odr-use 是否也适用于 extern 变量?但是那么 SIOF 应该就没有问题了吧?
猜你喜欢
  • 2021-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
相关资源
最近更新 更多