La vida útil de las static
variables de función comienza la primera vez [0] que el flujo del programa encuentra la declaración y termina al finalizar el programa. Esto significa que el tiempo de ejecución debe llevar a cabo una contabilidad para destruirlo solo si realmente se construyó.
Además, dado que el estándar dice que los destructores de objetos estáticos deben ejecutarse en el orden inverso a la finalización de su construcción [1] , y el orden de construcción puede depender del programa específico ejecutado, el orden de construcción debe tenerse en cuenta .
Ejemplo
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Salida:
C:> sample.exe
Creado en foo
Destruido en foo
C:> sample.exe 1
Creado en if
Creado en foo
Destruido en foo
Destruido en if
C:> sample.exe 1 2
Creado en foo
Creado en if
Destroyed en if
Destroyed en foo
[0]
Dado que C ++ 98 [2] no hace referencia a múltiples subprocesos, cómo se comportará esto en un entorno de subprocesos múltiples no está especificado y puede ser problemático como menciona Roddy .
[1]
Sección C ++ 98 3.6.3.1
[basic.start.term]
[2]
En C ++ 11, las estadísticas se inicializan de manera segura para subprocesos, esto también se conoce como Magic Statics .
[basic.start.term]
Motti tiene razón sobre el orden, pero hay algunas otras cosas a considerar:
Los compiladores suelen utilizar una variable de marca oculta para indicar si las estadísticas locales ya se han inicializado, y esta marca se verifica en cada entrada a la función. Obviamente, este es un pequeño éxito en el rendimiento, pero lo que es más preocupante es que no se garantiza que este indicador sea seguro para subprocesos.
Si tiene una estática local como la anterior y
foo
se llama desde varios subprocesos, es posible que las condiciones de carrera provoquenplonk
que se inicialicen de forma incorrecta o incluso varias veces. Además, en este casoplonk
puede ser destruido por un hilo diferente al que lo construyó.A pesar de lo que dice el estándar, desconfiaría del orden real de destrucción estática local, porque es posible que, sin saberlo, pueda confiar en que una estática sigue siendo válida después de que se haya destruido, y esto es realmente difícil de rastrear.
fuente
Las explicaciones existentes no están realmente completas sin la regla real del Estándar, que se encuentra en 6.7:
fuente
FWIW, Codegear C ++ Builder no se destruye en el orden esperado de acuerdo con el estándar.
... que es otra razón para no confiar en la orden de destrucción!
fuente
Las variables estáticas entran en juego una vez que comienza la ejecución del programa y permanecen disponibles hasta que finaliza la ejecución del programa.
Las variables estáticas se crean en el segmento de datos de la memoria .
fuente