2012-01-09 21 views
33

Lo que sé sobre C++ es que no se debe asumir el orden de las construcciones (y destrucciones) de las instancias globales.¿Está garantizado que std :: cout esté inicializado?

Mientras estoy escribiendo código con una instancia global que utiliza std::cout en el constructor & destructor, recibí una pregunta.

std::cout es también una instancia global de iostream. ¿Está garantizado que el std::cout se inicialice antes que cualquier otra instancia global?

Escribí un código de prueba simple y funciona perfectamente, pero aún no sé por qué.

#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; 
} 

Imprime

test::ctor 
Hello world 
test::dtor 

¿Hay alguna posibilidad de que el código no se ejecuta como se esperaba?

+1

Relacionados con http://stackoverflow.com/questions/6919593/is-cout-guaranteed-available-during-static-deinitialization que también cubre la construcción en la respuesta. – adl

+0

No se puede asumir el orden de inicialización de los objetos de duración de almacenamiento estático en el alcance global, pero hay trucos para forzar el orden de inicialización. –

+0

PD.También tenga en cuenta que el orden de destrucción está garantizado (el inverso de la construcción). –

Respuesta

36

La respuesta difiere según si usa C++ 03 o C++ 11.

En C++ 11, se garantiza que su código funciona, pero en C++ 03 no está especificado; su única garantía es que cuando se ingresa main(), las transmisiones estándar se han inicializado. (Dicho esto, todas las implementaciones de la corriente principal de ellos inicializan antes de ejecutar cualquier inicialización dinámica, por lo que bien para su uso.)

Puede forzar la inicialización mediante la construcción de un objeto std::ios_base::Init, así:

#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; 
} 

Ahora, cuando test construcciones, inicializa mInitializer y garantiza que las transmisiones estén listas para usar.

C++ 11 corrigió este comportamiento ligeramente molesto al actuar como si cada instancia de #include <iostream> fuera seguida por . Esto garantiza automáticamente que las transmisiones estén listas para usar.

+2

En C++ 03, la intención obvia (como lo indica la nota al pie) es garantizar que los objetos std :: cin/std :: cout estén completamente construidos antes que otros objetos. –

10

Según §27.3/2:

Los objetos [std :: cin, std :: cout, etc.] están construidos, y los asociaciones se establecen en algún momento antes de o durante la primera vez que se construye el objeto , se construye un objeto de la clase ios_base :: Init, y en cualquier caso antes de que el cuerpo principal comience la ejecución.

+1

Lo cual no dice nada sobre el orden de construcción de 'std :: cout' en relación con otros objetos estáticos. –

+10

@BasileStarynkevitch: cierto, pero la nota al pie 265 (referenciada en §27.3/2) dice que debería funcionar: "Los constructores y destructores de objetos estáticos pueden acceder a estos objetos para leer la entrada desde stdin o escribir salida en stdout o stderr". Eso puede no ser normativo, pero establece claramente al menos el * intento * de que su código debería funcionar. –

+3

@BasileStarynkevitch: En realidad sí. El párrafo continúa: "Los resultados de incluir en una unidad de traducción serán como si definieran una instancia de ios_base :: Init con una duración de almacenamiento estática." Y dado que las variables estáticas no locales en la misma unidad de traducción se inicializan en el orden de declaración, se garantiza que 'cout' se habrá inicializado antes que las otras estadísticas estáticas no locales. (Suponiendo que '#include ' antes de declarar sus variables, lo cual sinceramente espero) – knatten

2

Su pregunta es acerca del orden de construcción de los objetos estáticos. Creo que la especificación del lenguaje lo deja indefinido.

GCC tiene el atributo init_priority para jugar con la orden.

Y creo que no debería preocuparse tanto en la práctica.

Cuestiones relacionadas