iam*_*ind 6 c++ constructor iostream global-variables undefined-behavior
#include<iostream>
struct A {
A () {
std::cout << "A::A()\n";
}
};
A my_a; // works fine and prints the above line
int main () {}
Run Code Online (Sandbox Code Playgroud)
根据C++标准,未指定驻留在多个文件中的全局对象初始化的顺序.
即,在1个文件中定义的全局对象将按从上到下的顺序调用其构造函数.但是,如果有多个这样的文件,那么哪个文件将是倒数第一个,是实现定义的还是未指定的.
现在,std::cout和my_a都是全局对象.这意味着上面的代码是UB,它是正确的(即初始化惨败)?
可能,编译器可能足够聪明,可以std在移动到其他对象之前先初始化对象.仍然为了清楚起见,是否有任何完整的证明方法来执行跨多个文件的全局对象的日志记录?
是的,这是好的,而不是UB.声明的流的使用iostream由标准明确定义.
2 构造对象并在第一次
ios_base::Init构造类的对象之前或期间的某个时间建立关联,并且在任何情况下在main开始执行的主体之前建立关联.293在程序执行期间不会销毁对象.294 在翻译单元中包含的结果<iostream>应该像<iostream>定义ios_base::Init具有静态存储 持续时间的实例一样.类似地,整个程序的行为应该至少有一个ios_base::Init具有静态存储持续时间的实例.
因此,标准要求cout在首次创建之前进行初始化,ios_base::Init并#include<iostream>保证它将存在.因此,通过包含iostream,您可以隐式定义ios_base::Init静态实例并保证cout将正常工作.
另请注意,294明确指出允许静态对象的构造函数和析构函数使用这些对象.
294)静态对象的构造函数和析构函数可以访问这些对象以从stdin读取输入或将输出写入stdout或stderr.
C++ 03编辑:虽然之前给出的所有引用都是按照C++ 11进行的,而C++ 03没有" ios_base::Init在iostream include上定义"规则.C++ 03仍然有关于#260而不是294的静态对象的构造函数和析构函数的注释,因此对于C++ 03,它仍然允许在静态对象构造函数中使用cout.