静态存储中的内联变量何时初始化?

Dre*_*ann 5 c++ initialization-order c++17 inline-variable

C++ 标准(至少早于 C++17)已经说明了初始化顺序。

在同一翻译单元的命名空间范围内定义并动态初始化的静态存储持续时间的对象应按照其定义在翻译单元中出现的顺序进行初始化。

C++17 引入了内联变量,我相信这意味着可以在多个翻译单元中定义具有静态存储持续时间命名空间范围以及动态初始化的单个变量。

C++ 是否对这些变量的初始化顺序做出任何保证?

Bri*_*ian 5

参见 [basic.start.dynamic] p1:

如果变量是隐式或显式实例化的特化,则具有静态存储持续时间的非局部变量的动态初始化是无序的,如果变量是不是隐式或显式实例化的特化的内联变量,则是部分有序的,否则是有序的.

因此,您所描述的变量类型具有“部分有序初始化”。根据 p2:

非局部变量的动态初始化VW静态存储持续时间的顺序如下:

  • ...
  • 如果V有部分有序的初始化,W没有无序的初始化,并且V在定义W的每个翻译单元之前W定义,那么
    • 如果程序启动了主线程(6.6.1)以外的线程(4.7),则V强的初始化发生在 的初始化之前W
    • 否则, 的初始化V顺序在 的初始化之前W
  • ...

所以总结一下,假设图中没有实例化的模板:

  • 如果您有两个命名空间范围的内联变量,V并且在每个翻译单元中之前定义了W这些变量,那么在.VWVW
  • 如果 onlyV是内联的,并且W是在一个翻译单元中定义的某个非内联命名空间范围变量,VW只要在那个翻译单元中V的定义先于,就会在之前初始化W
  • 如果在内联变量之前定义了非内联变量,则无法保证它们的初始化顺序。

考虑初始化顺序的一种直观方式是,就像在 C++14 中一样,编译器按顺序初始化每个翻译单元,未指定不同翻译单元的相对顺序(它们可以相互交错),但是具有外部链接的内联变量被认为是在第一次实现“命中”其可能在任何翻译单元中的一个定义时被初始化。

另见 p5:

具有静态存储持续时间的非局部内联变量的动态初始化是否在main或的第一条语句之前排序是由实现定义的。如果它被推迟,它强烈发生在该变量的任何非初始化 odr 使用之前。它是由实现定义的,这种延迟的动态初始化发生在程序中的哪些线程和点上。