std::cout 是否保证被初始化?

2021-12-30 00:00:00 constructor global-variables c++

我对 C++ 的了解是,不应假定全局实例的构造(和销毁)顺序.

What I know about C++ is that the order of the constructions (and destructions) of global instances should not be assumed.

当我使用全局实例编写代码时,该实例在构造函数中使用 std::cout析构函数,我有个问题.

While I'm writing code with a global instance which uses std::cout in the constructor & destructor, I got a question.

std::cout 也是 iostream 的全局实例.std::cout 是否保证在任何其他全局实例之前初始化?

std::cout is also a global instance of iostream. Is std::cout guaranteed to be initialized before any other global instances?

我写了一个简单的测试代码,它运行良好,但我仍然不知道为什么.

I wrote a simple test code and it works perfectly, but still I don't know why.

#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

代码是否有可能没有按预期运行?

Is there any possibility that the code doesn't run as expected?

推荐答案

答案因您使用的是 C++03 还是 C++11 而异.

The answer differs depending on if you're using C++03 or C++11.

在 C++11 中,你的代码保证可以工作,但在 C++03 中它是未指定的;您唯一的保证是在输入 main() 时,标准流已经初始化.(也就是说,所有主流实现都会在运行任何动态初始化之前对它们进行初始化,从而使它们易于使用.)

In C++11, your code is guaranteed to work, but in C++03 it's unspecified; your only guarantee is that by the time main() is entered, the standard streams had been initialized. (That said, all mainstream implementations initialize them prior to running any dynamic initialization, making them fine to use.)

您可以通过构造一个 std::ios_base::Init 对象来强制初始化,如下所示:

You can force initialization by constructing an std::ios_base::Init object, like so:

#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 并保证流可以使用.

Now when test constructs, it initializes mInitializer and guarantees the streams are ready to use.

C++11 修复了这个有点烦人的行为,就像 #include 的每个实例后跟 static std::ios_base::Init __unspecified_name__;.这会自动保证流可以使用.

C++11 fixed this slightly annoying behavior by acting as if every instance of #include <iostream> were followed by static std::ios_base::Init __unspecified_name__;. This automatically guarantees the streams are ready to use.

相关文章