c++ - 在作为静态成员包含在另一个类中的类的构造函数中使用 cout

标签 c++ clang language-lawyer initialization-order

以下代码

#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 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).


您确实包括 <iostream>之前 B::a , 但初始化 B::a (B::astatic inline 变量)不是 ordered initialization 的一部分,所以可以在 std::ios_base::Init 之前初始化.似乎 Clang(至少在某些版本中)正是这样做的。这是一个有效的行为。
标准读取( [basic.start.dynamic] ):
  1. 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是部分有序的。
  1. 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::ainline静态变量或以某种方式强制 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/

相关文章:

c++ - 为他人写作

javascript - Clang 是否为 WebAssembly 的 memory.fill 和 memory.copy 提供内在函数?

C++ Vim clang complete 如何让 qt 自动完成?

c++ - C++ 中::运算符的规则

C++ 非常量-常量引用函数重载

C++汇编代码分析(用clang编译)

c++ - 如何将 Poco::Net::HTTPClientSession 的套接字设置为 TCP_NODELAY?

c - C 数组的大小返回意外值

c++ - C++ 编译器可以假定 const bool & value 不会改变吗?

javascript - 引用错误: can't access lexical declaration 'Foo' before initialization