以下代码
#include <iostream>
struct A {
A() {
std::cout << std::endl;
}
};
struct B {
static inline A a;
};
int main() {
}
用gcc 编译后成功,但用clang 编译后因段错误而崩溃。代码不标准还是叮当错了?https://godbolt.org/z/tEvfrW
最佳答案
Cppreference on std::ios_base::Init
reads :
The header
<iostream>
behaves as if it defines (directly or indirectly) an instance ofstd::ios_base::Init
with static storage duration: this makes it safe to access the standard I/O streams in the constructors and destructors of static objects with ordered initialization (as long as#include <iostream>
is included in the translation unit before these objects were defined).
您确实包括
<iostream>
之前 B::a
, 但初始化 B::a
(B::a
是 static inline
变量)不是 ordered initialization 的一部分,所以可以在 std::ios_base::Init
之前初始化.似乎 Clang(至少在某些版本中)正是这样做的。这是一个有效的行为。标准读取( [basic.start.dynamic] ):
- Dynamic initialization of a non-local variable with static storage duration is unordered if the variable is an implicitly or explicitly instantiated specialization, is partially-ordered if the variable is an inline variable that is not an implicitly or explicitly instantiated specialization, and otherwise is ordered.
所以,初始化
std::ios_base::Init
的实例已排序,并初始化 B::a
是部分有序的。
- Dynamic initialization of non-local variables
V
andW
with static storage duration are ordered as follows:3.1. If
V
andW
have ordered initialization and the definition ofV
is appearance-ordered before the definition ofW
, or ifV
has partially-ordered initialization,W
does not have unordered initialization, and for every definitionE
ofW
there exists a definitionD
ofV
such thatD
is appearance-ordered beforeE
, then ...3.2. Otherwise, if the program starts a thread other than the main thread before either
V
orW
is initialized, it is unspecified in which threads the initializations ofV
andW
occur; the initializations are unsequenced if they occur in the same thread.3.3. Otherwise, the initializations of
V
andW
are indeterminately sequenced.
3.1 和 3.2 不适用。所以我们有不确定的初始化顺序。
您可以制作
B::a
非 inline
静态变量或以某种方式强制 std::ios_base::Init
使用前初始化std::cout
, for example :struct A {
A() {
std::cout << std::endl;
}
std::ios_base::Init init;
};
关于c++ - 在作为静态成员包含在另一个类中的类的构造函数中使用 cout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62738001/