根据C ++ 11规范:
包含
<iostream>
在翻译单元中的结果应如同<iostream>
定义了ios_base::Init
具有静态存储持续时间的实例。同样,整个程序的行为应类似于至少一个ios_base::Init
具有静态存储持续时间的实例
这意味着如果我的代码如下所示:
// A.cpp
#include <iostream>
using namespace std;
unsigned long foo() {
cerr << "bar";
return 42;
}
和
// B.cpp
using namespace std;
extern unsigned long foo();
namespace {
unsigned long test() {
int id = foo();
return id;
}
unsigned long id = test();
}
int main() {
return 0;
}
那么我应该可以安全地进行呼叫,cerr
而不会出现静态初始化失败的风险。
不幸的是,该代码存在段错误...为什么?我不认为gcc 6.2.1决定忽略C ++ 11规范,而是将其包含<iostream>
在A.cpp中。根据规范,它就足够了。
该段的全引号包括:
在构造ios_base :: Init类的对象之前或第一次期间的某个时间,以及无论如何在main主体开始执行之前的某个时间,都将构造对象并建立关联。293)
还有脚注
293)如果他们有可能这样做,则鼓励实现比所需的早初始化对象。
因此,可以保证的是,iostream最迟在进入main时才能工作。没有严格的要求,除非翻译单位包括,否则它们应该更早地工作<iostream>
。
您已经找到一种规避此问题的方法!
foo()
从B.cpp调用时,A.cpp中ios_base::Init
包含的实例可能已初始化,也可能未初始化。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句