Гарантируется ли инициализация std :: cout? - PullRequest
38 голосов
/ 09 января 2012

Что я знаю о 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

Есть ли вероятность того, что код не работает должным образом?

Ответы [ 3 ]

41 голосов
/ 09 января 2012

Ответ зависит от того, используете ли вы 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__;. Это автоматически гарантирует, что потоки готовы к использованию.

10 голосов
/ 09 января 2012

Согласно §27.3 / 2 :

Объекты [std :: cin, std :: cout и т. Д.] Создаются, и ассоциации создаются в какое-то время до или во время первого раз создается объект класса ios_base :: Init, и в любом случае до того, как тело main начинает выполнение.

2 голосов
/ 09 января 2012

Ваш вопрос о порядке постройки статических объектов. Я считаю, что спецификация языка оставляет ее неопределенной.

GCC имеет атрибут init_priority для воспроизведения с ордером.

И я верю, что вам не стоит так сильно беспокоиться на практике.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...