C++ 下面的计划如何保证那里';将只是对象的一个定义,是吗。。。?

C++ 下面的计划如何保证那里';将只是对象的一个定义,是吗。。。?,c++,initialization,iostream,C++,Initialization,Iostream,您将在哪个标题下找到以下语句?: 最后,提供了八个标准全局对象(cin、, 库特等)。要正确执行此操作,此标题还提供 和标题的内容,但没有其他内容。这个 此标题的内容如下所示 #包括 #包括 名称空间标准 { 外间流cin; 外部环境; .... //下文对此进行解释 静态ios_base::Init _foo;//不是它的真名 } 现在,前面提到的运行时惩罚:全局对象必须 在您自己的任何代码使用它们之前进行初始化;这是 由标准保证。与任何其他全局对象一样,它们必须是 初始化一次且仅初始化一次

您将在哪个标题下找到以下语句?

最后,
提供了八个标准全局对象(cin、, 库特等)。要正确执行此操作,此标题还提供
标题的内容,但没有其他内容。这个 此标题的内容如下所示

#包括
#包括
名称空间标准
{
外间流cin;
外部环境;
....
//下文对此进行解释
静态ios_base::Init _foo;//不是它的真名
}
现在,前面提到的运行时惩罚:全局对象必须 在您自己的任何代码使用它们之前进行初始化;这是 由标准保证。与任何其他全局对象一样,它们必须是 初始化一次且仅初始化一次。这通常是通过一个 与上面的构造类似,嵌套类ios_base::Init是 正是出于这个原因在标准中规定的

它是如何工作的?因为标题包含在任何 代码中,_foo对象是在任何对象之前构造的。 (全局对象按声明顺序构建,以及 构造函数第一次运行时 设置了八个流对象


我的问题:当我在几个
.cpp
文件中包含头文件
时,上面的方案如何保证对象
cin
cout
等只有一个定义

这并不能保证这一点。只需在作为库的一部分的.cpp文件中定义一次流对象,即可解决单定义问题。问题中的代码只包含标准流的声明

可以保证的是,对象在使用之前将被初始化。C++中的全局对象的一个问题是,尽管它们在每个.CPP文件中都是按顺序初始化的,但我们不知道链接器将从单独的文件中放置对象的顺序。如果一个对象在初始化之前尝试使用另一个对象,并且我们不知道确切的顺序,那么这可能会导致问题-请参阅

这里使用的一种解决方法是在声明流对象的头中放置
Init
对象。因为在使用流之前必须包含头,所以我们知道这个
Init
对象将位于文件的顶部,因此在可能使用流的其他对象之前构造

现在,
Init
类的构造函数负责流对象的初始化。这必须尽早完成,而且只需一次。具体如何操作取决于每个实现,但代码提示使用计数器跟踪创建的
Init
对象的数量(可能会特别处理第一个)


这只是一种方法,只使用标准语言。有些实现还有其他技巧,比如s或指令,以说服链接器将库代码放在用户代码之前。在这种情况下,它只是神奇地工作,没有使用
Init
类。

这个“一个定义”并不有趣——它只是(编译的)标准库的一部分。有趣的是“一次初始化”。(我认为这项技术被称为。)AFAIK、
cout
cin
等。对象只是在标题中声明为
extern
,实际的定义在标准库的文件中。现在,
ios\u base::Init
被声明为
static
,因此每个翻译单元都有自己的副本。
Init
对象的构造函数/析构函数执行某种引用计数,以了解何时初始化/销毁标准流对象。至少你说的我都明白了。我不明白的是,当
包含在几个
.cpp
文件中时,
ios_base::Init
如何避免全局对象cin,cout,….的多个定义。就像我说的,
中没有定义它们,它们只是声明的。@jrok我将重新表述我的问题:上面的方案如何保证全局对象cin,cout,…,只有一个定义<代码>可以保证的是,对象在使用之前将被初始化。C++中的全局对象的一个问题是,尽管它们在每个.CPP文件中都是按顺序初始化的,但我们不知道链接器将从单独的文件中放置对象的顺序。如果一个对象在初始化之前尝试使用另一个对象,这可能会导致问题,我们不知道确切的顺序。据我所知,这个问题已经在C++11中解决了,至少根据这个答案,唯一的区别是在C++11中,实现的行为应该像构造
Init
对象一样。这也是它在C++03中的工作方式,只是没有详细说明(因为它被认为是显而易见的:-)。请参见
只需在作为库的一部分的.cpp文件中定义一次流对象,即可解决一个定义问题。
您是否有任何参考资料支持这一点?标准对此有什么规定吗?
#include <ostream>
#include <istream>

namespace std
{
    extern istream cin;
    extern ostream cout;
    ....

    // this is explained below
    static ios_base::Init __foo;    // not its real name
}