在 class 的构造函数中使用 cout 作为静态成员包含在另一个 class 中
Using cout in the constructor of a class that is included in another class as a static member
以下代码
#include <iostream>
struct A {
A() {
std::cout << std::endl;
}
};
struct B {
static inline A a;
};
int main() {
}
用gcc编译后成功,但用clang编译后由于分段错误而崩溃。是代码不规范还是clang错了?
std::ios_base::Init
上的 Cppreference reads:
The header <iostream>
behaves as if it defines (directly or indirectly) an instance of std::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).
您确实在 B::a
之前包含了 <iostream>
,但是 B::a
的初始化(B::a
是 static inline
变量)不是 [= 的一部分51=],所以可以在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
and W
with static storage duration are ordered as follows:
3.1. If V
and W
have ordered initialization and the definition of V
is appearance-ordered before the definition of W
, or if V
has partially-ordered initialization, W
does not have unordered initialization, and for every definition E
of W
there exists a definition D
of V
such that D
is appearance-ordered before E
, then ...
3.2. Otherwise, if the program starts a thread other than the main thread before either V
or W
is initialized, it is unspecified in which threads the initializations of V
and W
occur; the initializations are unsequenced if they occur in the same thread.
3.3. Otherwise, the initializations of V
and W
are indeterminately sequenced.
3.1 和 3.2 不适用。所以我们有不确定顺序的初始化。
您可以使 B::a
成为非 inline
静态变量或以某种方式强制 std::ios_base::Init
在使用 std::cout
、for example:[=54= 之前进行初始化]
struct A {
A() {
std::cout << std::endl;
}
std::ios_base::Init init;
};
以下代码
#include <iostream>
struct A {
A() {
std::cout << std::endl;
}
};
struct B {
static inline A a;
};
int main() {
}
用gcc编译后成功,但用clang编译后由于分段错误而崩溃。是代码不规范还是clang错了?
std::ios_base::Init
上的 Cppreference 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).
您确实在 B::a
之前包含了 <iostream>
,但是 B::a
的初始化(B::a
是 static inline
变量)不是 [= 的一部分51=],所以可以在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:[=54= 之前进行初始化]
struct A {
A() {
std::cout << std::endl;
}
std::ios_base::Init init;
};