c++ - programacion - Inicialización de objetos globales POD
objetos en c++ (4)
De acuerdo con el estándar C ++, 3.6.2.2: Inicialización de objetos no locales:
Juntos, la inicialización cero y la inicialización constante se llaman inicialización estática; el resto de la inicialización es inicialización dinámica. La inicialización estática se debe realizar antes de que tenga lugar cualquier inicialización dinámica.
Como myArrayOfPod
se myArrayOfPod
al menos a primera vista con una expresión constante, se debe inicializar antes de oSomeGlobalObject
. El hecho de que no está en depuración es probablemente un error. Puede enviar un error a través de connect.microsoft.com .
Me han picado hoy por un error.
Pregunta para los abogados de C ++
Consideremos la siguiente fuente:
struct MyPod
{
short m_short ;
const char * const m_string ;
} ;
MyPod myArrayOfPod[] = { { 1, "Hello" } } ;
int main(int argc, char * argv[])
{
return 0 ;
}
Tenga en cuenta que todos los valores se conocen en tiempo de compilación, y que MyPod es un POD.
Entonces, ¿se debe inicializar myArrayOfPod en tiempo de compilación, o el compilador generará algún constructor predeterminado de MyPod?
Detalles que incluyen una fuente independiente
La siguiente fuente que reproduce el error, se puede copiar / pegar en un archivo main.cpp:
#include <iostream>
// The point of SomeGlobalObject is for its
// constructor to be launched before the main
// ...
struct SomeGlobalObject
{
SomeGlobalObject() ;
} ;
// ...
// Which explains the global object
SomeGlobalObject oSomeGlobalObject ;
// A POD... I was hoping it would be constructed at
// compile time when using an argument list
struct MyPod
{
short m_short ;
const char * const m_string ;
} ;
// declaration/Initialization of a MyPod array
MyPod myArrayOfPod[] =
{ { 1, "Hello" }, { 2, "World" }, { 3, " !" } } ;
// declaration/Initialization of an array of array of void *
void * myArrayOfVoid[][2] =
{ { (void *)1, "Hello" }, { (void *)2, "World" }, { (void *)3, " !" } } ;
// constructor of the global object... Launched BEFORE main
SomeGlobalObject::SomeGlobalObject()
{
// The two values should be "1"
std::cout << "myArrayOfPod[0].m_short : " << myArrayOfPod[0].m_short << std::endl ;
std::cout << "myArrayOfVoid[0][0] : " << myArrayOfVoid[0][0] << std::endl ;
}
// main... What else ?
int main(int argc, char* argv[])
{
return 0 ;
}
MyPod siendo un POD, creí que no habría constructores. Solo inicialización en tiempo de compilación.
Por lo tanto, el objeto global SomeGlobalObject
no tendría ningún problema para utilizar la matriz global de POD en su construcción.
Pero, en Visual C ++ 2008, en modo de depuración, al ejecutar myArrayOfPod
no se inicializa correctamente (todos sus valores son zero-ed), incluso si myArrayOfVoid
se inicializó correctamente.
Así que mi pregunta es: ¿no se supone que los compiladores C ++ inicializan POD globales (incluidas las estructuras POD) en el momento de la compilación?
Displaimer
Tenga en cuenta que sé que las variables globales son malas, y sé que no se puede estar seguro del orden de creación de las variables globales declaradas en diferentes unidades de compilación, pero esto está fuera del tema: la pregunta es sobre la inicialización de POD global.
Editar
Copié / pegué este código en mi Ubuntu, y en lo que respecta a g ++ 4.4.3, las dos matrices se inicializan correctamente tanto en el modo de depuración como en el de liberación.
El comportamiento se informó a Microsoft y en espera de confirmación: https://connect.microsoft.com/VisualStudio/feedback/details/564844/pod-struct-global-object-initialization-uses-constructor
Editar 2
Visual C ++ QA respondió al envío de errores, citando el estándar (al menos, n3092 ). En lo que a ellos respecta, el comportamiento observado en Visual C ++ sigue el estándar.
Y a pesar de mi "sensación" de que esto sigue siendo un error, debo reconocer el hecho de que conocen el estándar infinitamente más que yo (aunque solo sea porque uso el lenguaje , cuando escriben un compilador para el idioma ), y así aceptan su respuesta .
Por lo tanto, haré mi tarea, es decir, leeré n3092 de principio a fin (Mil páginas de declaraciones como de abogado ... Esta es mi suerte ...): Este documento usa mucho bien- palabras definidas, y si no sé el significado exacto de cada palabra, entonces no hay manera de que pueda citar algún párrafo n3092 para apoyar mi punto de vista ...
Gracias a MSN y a AndreyT por sus respuestas.
El lenguaje C ++ garantiza que los objetos POD con duración de almacenamiento estático inicializados con expresiones constantes se inicializan de forma estática , es decir, "en tiempo de compilación". Más pedante, independientemente de cómo se implemente la inicialización estática (en tiempo de compilación, en tiempo de ejecución), debe tener lugar antes de cualquier inicialización dinámica. Una llamada de constructor, por ejemplo, es una inicialización dinámica.
En su caso myArrayOfPod
es un POD, los literales enteros son expresiones enteras constantes, y los literales de cadena son expresiones constantes de dirección. Diría que su myArrayOfPod
satisface todos los requisitos y, por lo tanto, debe inicializarse estáticamente. Si observa myArrayOfPod
no myArrayOfPod
del constructor de oSomeGlobalObject
en su experimento, debe ser un error en el compilador.
Para mí, parece que es un punto del orden en el que se inicializan los globales, no si lo son. Debe ser el modo de depuración que llama al código de inicialización global en un orden diferente al del modo de lanzamiento.
Globals haciendo referencia a los globales ... ¿puede haber grados de maldad? ;-)
Editar: Presumiblemente, si pones los dos cout en main, verás que todos los globals se han inicializado para cuando llegue allí.
¿No se supone que los compiladores C ++ inicializan POD globales (incluidas las estructuras POD) en el momento de la compilación?
No. ¿Cómo lo harían? Son construcciones en tiempo de ejecución. Incluso si el compilador incorporó todo en la descripción del programa (valores constantes en la pila), aún tiene que inicializarse en tiempo de ejecución.
IRC, dentro de la misma unidad de traducción, se garantiza que el orden de inicialización de los valores globales esté en orden de declaración. Considere dónde coloca su objeto global dentro del archivo.
Si me equivoco sobre eso, el orden no está definido. Además, cuando hablamos de globales en las unidades de traducción, el orden no está definido. De eso estoy seguro.