Estoy bastante seguro de que las variables declaradas globalmente se asignan (e inicializan, si corresponde) en el momento de inicio del programa.
int globalgarbage;
unsigned int anumber = 42;
Pero, ¿qué pasa con los estáticos definidos dentro de una función?
void doSomething()
{
static bool globalish = true;
// ...
}
¿Cuándo se globalish
asigna el espacio ? Supongo que cuando comienza el programa. ¿Pero también se inicializa entonces? ¿O se inicializa cuando doSomething()
se llama por primera vez?
Algunas palabras relevantes del estándar C ++:
fuente
If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration.
La memoria para todas las variables estáticas se asigna al cargar el programa. Pero las variables estáticas locales se crean e inicializan la primera vez que se utilizan, no al iniciar el programa. Hay una buena lectura sobre eso, y estática en general, aquí . En general, creo que algunos de estos problemas dependen de la implementación, especialmente si desea saber en qué parte de la memoria se ubicarán estas cosas.
fuente
El compilador asignará variables estáticas definidas en una función
foo
al cargar el programa, sin embargo, el compilador también agregará algunas instrucciones adicionales (código de máquina) a su funciónfoo
para que la primera vez que se invoque este código adicional inicializará la variable estática ( por ejemplo, invocando al constructor, si corresponde).@Adam: Esta inyección de código detrás de escena por parte del compilador es la razón del resultado que vio.
fuente
Intento probar nuevamente el código de Adam Pierce y agregué dos casos más: variable estática en clase y tipo POD. Mi compilador es g ++ 4.8.1, en el sistema operativo Windows (MinGW-32). El resultado es una variable estática en la clase que se trata igual que la variable global. Su constructor será llamado antes de ingresar a la función principal.
Conclusión (para g ++, entorno Windows):
(1) : El estado correcto debe ser: "antes de que se llame a cualquier función de la misma unidad de traducción". Sin embargo, por simple, como en el ejemplo siguiente, entonces es la función principal .
incluir <iostream>
#include < string> using namespace std; class test { public: test(const char *name) : _name(name) { cout << _name << " created" << endl; } ~test() { cout << _name << " destroyed" << endl; } string _name; static test t; // static member }; test test::t("static in class"); test t("global variable"); void f() { static test t("static variable"); static int num = 10 ; // POD type, init before enter main function test t2("Local variable"); cout << "Function executed" << endl; } int main() { test t("local to main"); cout << "Program start" << endl; f(); cout << "Program end" << endl; return 0; }
resultado:
static in class created global variable created local to main created Program start static variable created Local variable created Function executed Local variable destroyed Program end local to main destroyed static variable destroyed global variable destroyed static in class destroyed
¿Alguien probado en Linux env?
fuente
Sí lo es. Esto, entre otras cosas, le permite inicializar estructuras de datos de acceso global cuando sea apropiado, por ejemplo, dentro de bloques try / catch. Por ejemplo, en lugar de
int foo = init(); // bad if init() throws something int main() { try { ... } catch(...){ ... } }
puedes escribir
int& foo() { static int myfoo = init(); return myfoo; }
y utilícelo dentro del bloque try / catch. En la primera llamada, la variable se inicializará. Luego, en la primera y la siguiente llamada, se devolverá su valor (por referencia).
fuente
Las variables estáticas se asignan dentro de un segmento de código; son parte de la imagen ejecutable y, por lo tanto, se asignan ya inicializadas.
Las variables estáticas dentro del alcance de la función se tratan de la misma manera, el alcance es puramente una construcción de nivel de lenguaje.
Por esta razón, tiene la garantía de que una variable estática se inicializará en 0 (a menos que especifique algo más) en lugar de un valor indefinido.
Hay algunas otras facetas de la inicialización que puede aprovechar; por ejemplo, los segmentos compartidos permiten que diferentes instancias de su ejecutable se ejecuten a la vez para acceder a las mismas variables estáticas.
En C ++ (de ámbito global) los objetos estáticos tienen sus constructores llamados como parte del inicio del programa, bajo el control de la biblioteca de tiempo de ejecución de C. En Visual C ++, al menos el orden en el que se inicializan los objetos se puede controlar mediante el pragma init_seg .
fuente