我对C ++的了解是不应该假设全局实例的构造(和析构)的顺序。
我正在使用构造函数&中使用std::cout
的全局实例编写代码。析构函数,我有一个问题。
std::cout
也是iostream的全局实例。是否保证std::cout
在任何其他全局实例之前被初始化?
我写了一个简单的测试代码,它运行得很好,但我仍然不知道为什么。
#include <iostream>
struct test
{
test() { std::cout << "test::ctor" << std::endl; }
~test() { std::cout << "test::dtor" << std::endl; }
};
test t;
int main()
{
std::cout << "Hello world" << std::endl;
return 0;
}
打印
test::ctor
Hello world
test::dtor
代码是否有可能无法按预期运行?
答案 0 :(得分:40)
答案取决于您使用的是C ++ 03还是C ++ 11。
在C ++ 11中,您的代码保证可以正常工作,但在C ++ 03中,它是未指定的;您唯一的保证是,在输入main()
时,标准流已初始化。 (也就是说,所有主流实现在运行任何动态初始化之前都会对它们进行初始化,这样可以很好地使用它们。)
您可以通过构建std::ios_base::Init
对象强制进行初始化,如下所示:
#include <iostream>
struct test
{
test() { std::cout << "test::ctor" << std::endl; }
~test() { std::cout << "test::dtor" << std::endl; }
private:
std::ios_base::Init mInitializer;
};
test t;
int main()
{
std::cout << "Hello world" << std::endl;
return 0;
}
现在test
构建时,它会初始化mInitializer
并保证流可以使用。
C ++ 11修复了这种有点恼人的行为,就好像#include <iostream>
的每个实例都跟着static std::ios_base::Init __unspecified_name__;
一样。这样可以自动保证流可以使用。
答案 1 :(得分:10)
根据§27.3/ 2 :
构造对象[std :: cin,std :: cout等],并且 在第一次之前或期间的某个时间建立关联 时间构建ios_base :: Init类的对象,无论如何 在主体开始执行之前。
答案 2 :(得分:2)