在静态对象的析构函数中使用 cout

Using cout in destructors of static objects

提问人:Paul J. Lucas 提问时间:2/22/2014 最后编辑:Paul J. Lucas 更新时间:1/5/2017 访问量:1742

问:

鉴于我的代码的这个精简版本:

#include <iostream>

using namespace std;

struct S {
  S( ostream &os ) : os_( os ) { }
  ~S() { os_ << "The end.\n"; }         // line 7
  ostream &os_;
};

void f() {
  static S s( cout );
  (void)s;
}

int main() {
  f();
  return 0;
}

程序打印 但是,作为较大程序的一部分,它在尝试写入 时出现 SEGFAULTS。The end.ostream

我正在努力确保在程序终止时始终打印一些文本。我尝试使用 iostreams 做的事情合法吗?使用会更好吗?atexit(3)

我以为,因为在我使用它之前建造了它,之后它就会被摧毁;因此,目前尚不清楚为什么像上面这样的代码不应该总是有效。cout

更新

如果我将第 7 行更改为直接写入而不是通过引用,它可以正常工作。这更奇怪。cout

C++ 析构函数 iostream static-variables

评论

2赞 Jonathan Potter 2/22/2014
对我而言,保留对一个你无法控制其生命周期的对象的引用似乎是个坏主意。
0赞 David G 2/22/2014
@JonathanPotter 是静态的,就像 is 的实例一样,这就是他询问行为的原因。std::coutS
2赞 Gort the Robot 2/22/2014
静态对象的创建和销毁没有定义的顺序,因此当另一个静态对象被销毁时,您不能依赖在场。cout
0赞 Paul J. Lucas 2/22/2014
什么??我以为静态物体的破坏总是以相反的构造顺序进行。
1赞 Collin Dauphinee 2/22/2014
我不确定标准对此有何规定,但我知道有些编译器不认为将引用作为“首次使用”。必须实际访问该对象。gcc 是最大的罪魁祸首,尽管我不确定最新版本。

答:

0赞 Curious 1/5/2017 #1

如果在构造静态对象之后调用,则静态对象将在调用该对象后被销毁。所以是的,使用应该可以解决问题。atexit()atexit()

请参阅 C++ 中全局对象销毁和退出之间的顺序