在作为静态成员包含在另一个类中的类的构造函数中使用 cout
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 编译后因分段错误而崩溃。是代码不标准还是叮当错了?
https://godbolt.org/z/tEvfrW
Cpp首选项对std::ios_base::Init
如下:
标头
<iostream>
的行为就像它(直接或间接(定义具有静态存储持续时间的std::ios_base::Init
实例一样:这使得访问静态对象的构造函数和析构函数中的标准 I/O 流变得安全有序初始化(只要在定义这些对象之前#include <iostream>
包含在转换单元中(。
您确实在B::a
之前包含<iostream>
,但B::a
的初始化(B::a
static inline
变量(不是有序初始化的一部分,因此可以在std::ios_base::Init
之前初始化。似乎Clang(至少某些版本(正是这样做的。这是一种有效的行为。
标准如下([basic.start.dynamic](:
如果具有静态存储持续时间的非局部变量是隐式或显式实例化的专用化,则动态初始化是
- 无序的;如果变量是不是隐式或显式实例化的内联变量,则动态初始化是部分有序的,否则是有序的。
因此,std::ios_base::Init
实例的初始化是有序的,B::a
的初始化是部分有序的。
具有
- 静态存储持续时间的非局部变量
V
和W
的动态初始化顺序如下:3.1.如果
V
和W
有有序初始化,并且V
的定义在W
定义之前是外观有序的,或者如果V
有部分有序的初始化,W
没有无序初始化,并且对于W
的每个定义E
都存在一个定义D
V
使得D
在E
之前是外观有序的, 然后。。。3.2. 否则,如果程序在初始化
V
或W
之前启动主线程以外的线程,则未指定初始化V
和W
在哪些线程中进行;如果初始化发生在同一线程中,则初始化是未排序的。3.3. 否则,
V
和W
的初始化将不确定地排序。
3.1 和 3.2 不适用。所以我们有不确定的顺序初始化。
您可以在使用std::cout
之前将B::a
设置为非inline
静态变量或以某种方式强制std::ios_base::Init
初始化,例如:
struct A {
A() {
std::cout << std::endl;
}
std::ios_base::Init init;
};
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- 一对向量构造函数:初始值设定项列表与显式构造
- 从构造函数抛出异常时如何克服内存泄漏
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 具有默认模板类型的默认构造函数的类型推导
- 在作为静态成员包含在另一个类中的类的构造函数中使用 cout
- Cin和Cout在构造函数中
- 在构造函数中 'cout' 未在此范围内声明