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