考虑这个例子:
#include <iostream>
struct A {
A() {
std::cout<<"hello" << std::endl;
}
};
inline A a;
int main() {
}
这个例子导致Clang 15下的程序段,改为
#include <iostream>
struct A {
A() {
std::cout<<"hello" << std::endl;
}
};
static inline A a;
int main() {
}
此示例成功打印
hello
。在这两种情况下,说明符static
,IMO,不应该影响std::cout
和变量a
的初始化顺序,它们的初始化顺序都是不确定的,对吧?
简而言之,您所看到的差异是可能的,但这纯粹是巧合。 使用
static
而不使用 inline
以确保安全;否则初始化顺序不可靠。
如果变量是隐式或显式实例化的专门化,则具有静态存储持续时间的非块变量的动态初始化是无序的;如果变量是不是隐式或显式实例化的专门化的内联变量,则该变量是部分有序的,否则是已订购。
inline A
和static inline A
都具有部分有序的初始化。
因为在任何一种情况下
#include <iostream>
都出现在 a
的声明之前,所以在这两种情况下,std::cout
的初始化都是 appearance-ordered 在 a
之前,但仅在您的翻译单元中,而不是在标准库。
如果我们认为标准库可能有额外的TU(
std::cout
的定义所在),那么[basic.start.dynamic] p3.1不适用,因此std::cout
的初始化不适用必然发生在 a
初始化之前。
适用的项目符号是 [basic.start.dynamic] p3.3:
在这种情况下,否则,V [
]和W [std::cout
]的初始化是不确定顺序的。a
static
只是给出了变量的内部链接,这对措辞没有任何影响。
它解决您的问题纯属巧合。
另请注意,static inline
对于变量来说基本上没有意义,您可以只使用 static
来代替。
在这种情况下,std::cout
和a
都已有序初始化,并且std::cout
始终会在a
之前初始化。