C++ 标准是不是保证 cin、cout 等会先创建后销毁?

Posted

技术标签:

【中文标题】C++ 标准是不是保证 cin、cout 等会先创建后销毁?【英文标题】:Is it guaranteed by the C++ standard that cin, cout, etc. will be created first and destroyed last?C++ 标准是否保证 cin、cout 等会先创建后销毁? 【发布时间】:2014-11-21 11:03:48 【问题描述】:

cincout,与基本流相关 - 标准中的任何地方都保证这些对象将首先创建并最后销毁吗?

这意味着非本地静态对象可以在其构造函数和析构函数中依赖它们(这些对象和基本流之间没有 ctor 竞争)。

【问题讨论】:

【参考方案1】:

保证在包含<iostream> 之后声明的任何静态对象之前创建它们,并且无论如何,在启动main 之前。它们在程序执行期间不会被销毁。

包含标头具有声明ios_base::Init 类型的静态变量的效果,其创建确保标准流被初始化。

如果你想要这个标准的:

C++11 27.4.1 [iostream.objects.overview]/2:在第一次构造类 ios_base::Init 的对象之前或期间的某个时间构造对象并建立关联,并且无论如何,在 main 的主体开始执行之前。在程序执行期间对象不会被破坏。在翻译单元中包含<iostream> 的结果应如同<iostream> 定义了具有静态存储持续时间的ios_base::Init 实例。同样,整个程序的行为就好像至少有一个具有静态存储持续时间的ios_base::Init 实例。

【讨论】:

main 不是唯一的东西,程序员会写。全局变量和静态变量也是候选对象。 @Ajay:确实,这就是为什么main 不是我唯一提到的原因。正如我所说,保证在包含<iostream> 之后声明的任何静态对象之前创建流。 我不是说你错了迈克,但我怀疑。原因:我可能有多个标题,包含在正确的顺序(或不包含)。不能保证第一个标头会按照给定的顺序放入链接器/加载器的初始化阶段。还是有保证?如果不是,则包含 <iostream> 只不过是文本包含。是的,我知道流类的实际代码驻留在运行时库(DLL、SO 或静态库)中。如果是这种情况,是否可以保证首先初始化 DLL/SO/LIB 对象?再次,那里的订单保证是什么? @Ajay:我已经准确地说明了保证是什么。如果您包含标头(保证在包含点插入其内容),则随后在同一翻译单元中声明的任何静态对象(因此库等与此无关)将在流之后初始化。如果您声明一个静态对象而不首先包含标头,则无法保证。 @hauron Mike 的回答给出了字面规则。我没有在回答中重复它们,因为它们已经被陈述过了。我之所以回答是因为我认为值得描述这些保证的限制,但如果没有 Mike 的保证,我的回答是不完整的。【参考方案2】:

您的问题的简单答案是否定的。正如其他人指出的那样, 翻译单元中定义的对象保证 包括<iostream>,至少如果对象是在 包容。但这并不总是有帮助:您将 <iostream> 包含在 定义构造函数的翻译单元,不一定在 定义静态变量的那个。所以像下面这样的情况 是可能的:

file1.hh

class X

public:
    X();
;

file1.cc

#include "file1.hh"
#include <iostream>

X::X()

    std::cout << "Coucou, me voila!" << std::endl;

file2.cc

#include "file1.hh"

X anX;

在这种情况下,anX 的构造函数很有可能是 在构造 std::cout 之前调用。

为了安全起见:如果一个对象的构造函数可能是 用作静态变量想要使用任何标准流,它 应该可能声明一个ios_base::Init 类型的本地静态:

X::X()

    static ios_base::Init dummyForInitialization;
    std::cout << "Coucou, me voila!" << std::endl;

如果std::cout 在此构造函数被构造时尚未构造 调用,将在构造静态变量时进行。

【讨论】:

感谢有用的例子“假装”是 cout/cin 安全 :) +1 反例。 从实际的角度来看,这个答案更有用 - 它显示了一个示例以及如何解决问题。该问题询问了标准,但我确实相信这些答案共同构成了“完美答案”,因此我选择了 Mike 的答案,并为此投票。

以上是关于C++ 标准是不是保证 cin、cout 等会先创建后销毁?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 标准是不是保证统一初始化是异常安全的?

c++中的cin 和cout 有啥用怎么用 >> <<有啥用怎么用

C++中cin和cout的具体用法是怎么样的?

c++中scanf和cout有啥区别

在c++中cin,cout都叫啥? 主函数吗?

cin和cout分别是哪两个类的对象