C++ 标准(至少早于 C++17)已经说明了初始化顺序。
在同一翻译单元的命名空间范围内定义的静态存储持续时间并动态初始化的对象应按照其定义在翻译单元中出现的顺序进行初始化。
C++17 引入了内联变量,我认为这意味着可以在多个翻译单元中定义具有静态存储持续时间和命名空间范围以及动态初始化的单个变量。
C++ 是否对这些变量的初始化顺序做出任何保证?
C++ 标准(至少早于 C++17)已经说明了初始化顺序。
在同一翻译单元的命名空间范围内定义的静态存储持续时间并动态初始化的对象应按照其定义在翻译单元中出现的顺序进行初始化。
C++17 引入了内联变量,我认为这意味着可以在多个翻译单元中定义具有静态存储持续时间和命名空间范围以及动态初始化的单个变量。
C++ 是否对这些变量的初始化顺序做出任何保证?
参见 [basic.start.dynamic] p1:
如果变量是隐式或显式实例化的特化,则具有静态存储持续时间的非局部变量的动态初始化是无序的,如果变量是不是隐式或显式实例化的特化的内联变量,则它是部分排序的,否则是有序的.
因此,您描述的变量类型具有“部分有序初始化”。根据p2:
非局部变量的动态初始化
V
和W
静态存储持续时间的顺序如下:
- ...
- 如果
V
有部分有序的初始化,W
没有无序的初始化,并且V
在定义W
的每个翻译单元之前W
定义,那么
- 如果程序启动主线程(6.6.1)以外的线程(4.7),
V
强烈的初始化发生在初始化之前W
;- 否则, 的初始化将
V
在 的初始化之前进行W
。- ...
所以总结一下,假设图中没有实例化的模板:
V
,并且在每个翻译单元之前定义W
,则在之前初始化。V
W
V
W
V
是内联的,并且W
是恰好在一个翻译单元中定义的某个非内联命名空间范围变量,则只要在该翻译单元中' 的定义在'V
之前,就会被初始化。W
V
W
考虑初始化顺序的一种直观方式是,就像在 C++14 中一样,编译器按顺序初始化每个翻译单元,但未指定不同翻译单元的相对顺序(它们可以相互交错),但是具有外部链接的内联变量被认为是在实现第一次“命中”其定义之一时被初始化,该定义可能位于任何翻译单元中。
另见 p5:
具有静态存储持续时间的非局部内联变量的动态初始化是在第一个语句之前排序
main
还是延迟是由实现定义的。如果它被延迟,它强烈发生在该变量的任何非初始化 odr 使用之前。它是实现定义的,在哪些线程和程序中的哪些点发生这种延迟的动态初始化。