[英]Static-storage-duration initialization
在C ++中,静态存储持续时间对象以未指定的顺序初始化(同一编译单元中除外)。
使用如下代码:
#include <iostream>
struct Foo {
Foo() {
std::cout << "Hello, world.\n";
}
} foo_instance;
int main(int argc, const char *argv[]) {
return 0;
}
在标准中规定的位置,我可以在foo_instance
初始化期间使用std::cout
吗?
我知道我可以通过在<iostream>
添加一些技巧来确保一切正常,例如,让它包含类似
int __ensure_stdout_initialization_call();
namespace {
int __ensure_stdout_initialization
= __ensure_stdout_initialization_call();
}
但是,问题在于,对于标准库所需的所有初始化,在哪里可以保证做到这一点。
我不确定标准(*)中是否明确声明了它,但是通常std :: cin , std :: cout和std :: cerr是在Nifty Counter习惯用法的帮助下实现的。
基本思想是在头文件中包含一个辅助静态对象,该对象在初始化期间检查流对象是否已被初始化,如果没有,则对其进行初始化。 通常首先包括这样的内容,即在相同转换单元中的任何其他静态对象之前初始化此类辅助静态对象,并确保在任何其他静态对象可以引用它之前对流对象进行适当的初始化。
(*) 编辑:
这是标准草案N3936中的适当措词:
27.4标准iostream对象
27.4.1.2
在构造ios_base :: Init类的对象之前或第一次期间的某个时间,并且无论如何在main主体开始执行之前或之前的某个时间,构造对象并建立关联。 程序执行期间不会破坏对象。 在转换单元中包含<iostream>的结果应类似于定义了具有静态存储持续时间的ios_base :: Init实例。 同样,整个程序的行为就好像至少有一个ios_base :: Init实例具有静态存储持续时间一样。
TL;博士; 在foo_instance
初始化期间,不应使用std::cout
。
无论标准中标准流的初始化如何,唯一的要求是
27.4.1概述[iostream.objects.overview]
3在构造
ios_base::Init
类的对象之前或第一次期间的某个时间,以及无论如何在main主体开始执行之前的某个时间,都将构造对象并建立关联。 291在程序执行过程中未破坏对象。 292在转换单元中包含<iostream>
的结果应类似于<iostream>
定义了具有静态存储持续时间的ios_base::Init
实例。
因此,如果在声明静态变量之前包含<iostream>
,则可以保存,因为根据标准
3.6.3非局部变量的动态初始化[basic.start.dynamic]
2具有静态存储持续时间的非局部变量V和W的动态初始化的顺序如下:(2.1)如果V和W进行了顺序初始化,并且V在单个转换单元中的W之前定义,则V的初始化在V的初始化之前进行。 W的初始化
因此, ios_base::Init
将在变量和标准流准备就绪之前初始化,但是,如果在包含<iostream>
之前声明变量,似乎仍然可以自行解决:
struct Foo
{
Foo();
} foo_instance; // uses ::std::cout
#include <iostream> // declares ios_base::Init variable that will init ::std::cout
Foo::Foo()
{
std::cout << "Hello, world.\n";
}
int main(int argc, const char *argv[]) {
return 0;
}
因此,我可以得出结论,在非局部变量的动态初始化期间不能使用std :: cout。
看一下标题<iostream>
。
该标准说,它的行为就像定义了一个std::ios_base::Init
类型的TU本地对象一样,该对象处理初始化并最终冲洗标准流。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.