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