6

根据 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 中。根据规范应该足够了。

4

1 回答 1

7

该段的完整引用包括:

在第一次构造 ios_base::Init 类的对象之前或期间,构建对象并建立关联,并且无论如何在 main 的主体开始执行之前。293)

并带有脚注

293)如果他们可以这样做,鼓励实现比要求更早地初始化对象。

因此,保证 iostream最迟在进入 main 时会工作。没有严格要求他们应该早点工作,除非翻译单元包括<iostream>.

你已经找到了一种方法来规避这个!

foo()从 B.cpp调用时,A.cpp 中ios_base::Init包含的实例可能已初始化,也可能未初始化。

于 2016-10-20T16:54:23.203 回答