c++ - usar - variable static java
¿Cuál es el tiempo de vida de una variable estática en una función de C++? (4)
FWIW, Codegear C ++ Builder no se destruye en el orden esperado según el estándar.
C:/> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if
... que es otra razón para no confiar en la orden de destrucción!
Si una variable se declara como static
en el alcance de una función, solo se inicializa una vez y conserva su valor entre las llamadas de función. ¿Qué es exactamente su vida? ¿Cuándo se llama a su constructor y destructor?
void foo()
{
static string plonk = "When will I die?";
}
La vida útil de las variables static
de función comienza la primera vez que [0] el flujo del programa encuentra la declaración y finaliza al finalizar el programa. Esto significa que el tiempo de ejecución debe realizar algún mantenimiento de libros para destruirlo solo si se construyó realmente.
Además, como la norma dice que los destructores de objetos estáticos deben ejecutarse en el orden inverso a la finalización de su construcción [1] y que 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 fooC:> sample.exe 1
Creado en si
Creado en foo
Destruido en foo
Destruido en siC:> sample.exe 1 2
Creado en foo
Creado en si
Destruido en si
Destruido en foo
[0]
Dado que C ++ 98 [2] no tiene referencia a varios subprocesos, no se especifica cómo se comportará esto en un entorno de subprocesos múltiples, y puede ser problemático, como menciona Roddy .
[1]
C ++ 98 sección 3.6.3.1
[basic.start.term]
[2]
En C ++ 11, las estadísticas están inicializadas de una manera segura para subprocesos, esto también se conoce como Magic Statics .
Las explicaciones existentes no están realmente completas sin la regla real del Estándar, que se encuentra en 6.7:
La inicialización cero de todas las variables de ámbito de bloque con la duración del almacenamiento estático o la duración del almacenamiento de subprocesos se realiza antes de que tenga lugar cualquier otra inicialización. La inicialización constante de una entidad de ámbito de bloque con duración de almacenamiento estático, si corresponde, se realiza antes de que se ingrese por primera vez. Se permite que una implementación realice una inicialización temprana de otras variables de ámbito de bloque con una duración de almacenamiento de subprocesos o estática en las mismas condiciones en que se permite que una implementación inicialice estáticamente una variable con una duración de almacenamiento de subprocesos o estática en el ámbito de espacio de nombres. De lo contrario, tal variable se inicializa la primera vez que el control pasa a través de su declaración; dicha variable se considera inicializada una vez finalizada su inicialización. Si la inicialización sale al lanzar una excepción, la inicialización no está completa, por lo que se intentará nuevamente la próxima vez que el control ingrese a la declaración. Si el control ingresa la declaración al mismo tiempo mientras se inicializa la variable, la ejecución concurrente esperará a que se complete la inicialización. Si el control reingresa recursivamente la declaración mientras la variable se está inicializando, el comportamiento no está definido.
Motti tiene razón sobre el pedido, pero hay algunas otras cosas a considerar:
Los compiladores suelen utilizar una variable de bandera oculta para indicar si las estadísticas locales ya se han inicializado, y esta bandera se comprueba en cada entrada a la función. Obviamente, este es un pequeño golpe de 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 se llama a ''foo'' desde varios subprocesos, es posible que haya condiciones de carrera que hagan que ''plonk'' se inicialice incorrectamente o incluso varias veces. Además, en este caso, ''plonk'' puede ser destruido por un hilo diferente al que lo construyó.
A pesar de lo que dice la norma, desconfiaría del orden real de destrucción estática local, porque es posible que, sin saberlo, confíe en que un estático siga siendo válido después de que haya sido destruido, y esto es realmente difícil de rastrear.