programas programación para ingenieros ejemplos dev completo comandos clases basicos c++ static-variables static-order-fiasco initialization-order

programación - Orden de inicialización estática de C++



manual completo de c++ pdf (6)

De hecho, esto funciona. Lamentablemente, tiene que escribir globalObject (). MemberFunction (), en lugar de globalObject.MemberFunction (), lo que resulta en un código de cliente algo confuso y poco elegante.

Pero lo más importante es que funciona, y que es a prueba de fallas, es decir. no es fácil pasar por alto el uso correcto.

La corrección del programa debe ser su primera prioridad. Además, en mi humilde opinión, el () anterior es puramente estilístico, es decir. completamente sin importancia.

Según su plataforma, tenga cuidado con demasiada inicialización dinámica. Hay una cantidad relativamente pequeña de limpieza que puede tener lugar para los inicializadores dinámicos (consulte here ). Puede resolver este problema utilizando un contenedor de objetos global que contiene miembros de objetos globales diferentes. Por lo tanto, tienes:

Globals & getGlobals () { static Globals cache; return cache; }

Solo hay una llamada a ~ Globals () para limpiar todos los objetos globales en su programa. Para acceder a un global, todavía tienes algo como:

getGlobals().configuration.memberFunction ();

Si realmente quisiera, podría envolver esto en una macro para guardar un poco de tipeo usando una macro:

#define GLOBAL(X) getGlobals().#X GLOBAL(object).memberFunction ();

Aunque, esto es solo azúcar sintáctico en su solución inicial.

Cuando uso variables estáticas en C ++, a menudo termino deseando inicializar una variable pasando otra a su constructor. En otras palabras, quiero crear instancias estáticas que dependan entre sí.

Dentro de un único archivo .cpp o .h esto no es un problema: las instancias se crearán en el orden en que se declaran. Sin embargo, cuando desea inicializar una instancia estática con una instancia en otra unidad de compilación, el orden parece imposible de especificar. El resultado es que, dependiendo del clima, puede ocurrir que la instancia que depende de otra se construya, y solo después se construya la otra instancia. El resultado es que la primera instancia se inicializa incorrectamente.

¿Alguien sabe cómo garantizar que los objetos estáticos se crean en el orden correcto? He buscado mucho tiempo para encontrar una solución, probándolos a todos (incluida la solución Schwarz Counter), pero empiezo a dudar de que haya uno que realmente funcione.

Una posibilidad es el truco con el miembro de la función estática:

Type& globalObject() { static Type theOneAndOnlyInstance; return theOneAndOnlyInstance; }

De hecho, esto funciona. Lamentablemente, tiene que escribir globalObject (). MemberFunction (), en lugar de globalObject.MemberFunction (), lo que resulta en un código de cliente algo confuso y poco elegante.

Actualización: Gracias por sus reacciones. Lamentablemente, parece que he respondido mi propia pregunta. Creo que tendré que aprender a vivir con eso ...


A pesar de la edad de este hilo, me gustaría proponer la solución que he encontrado. Como muchos han señalado antes que yo, C ++ no proporciona ningún mecanismo para la ordenación de inicialización estática. Lo que propongo es encapsular cada miembro estático dentro de un método estático de la clase que, a su vez, inicializa al miembro y proporciona un acceso orientado a objetos. Permítanme darles un ejemplo, supongamos que queremos definir la clase llamada "Matemáticas" que, entre los otros miembros, contiene "PI":

class Math { public: static const float Pi() { static const float s_PI = 3.14f; return s_PI; } }

s_PI se inicializará la primera vez que se invoca el método Pi () (en GCC). Tenga en cuenta: los objetos locales con almacenamiento estático tienen un ciclo de vida dependiente de la implementación, para mayor detalle, verifique 6.7.4 en 2 .

Palabra clave estática , 2


Envolver la estática en un método solucionará el problema del pedido, pero no es seguro para subprocesos, como otros han señalado, pero puede hacerlo para que también lo haga si es una preocupación.

// File scope static pointer is thread safe and is initialized first. static Type * theOneAndOnlyInstance = 0; Type& globalObject() { if(theOneAndOnlyInstance == 0) { // Put mutex lock here for thread safety theOneAndOnlyInstance = new Type(); } return *theOneAndOnlyInstance; }


La mayoría de los compiladores (vinculadores) realmente admiten una forma (no portátil) de especificar el pedido. Por ejemplo, con Visual Studio puede usar init_seg pragma para organizar la inicialización en varios grupos diferentes. AFAIK no hay forma de garantizar el orden DENTRO de cada grupo. Como esto no es portátil, puede considerar si puede reparar su diseño para no requerirlo, pero la opción está disponible.


Tal vez deberías reconsiderar si necesitas tantas variables estáticas globales. Si bien a veces pueden ser útiles, a menudo es mucho más simple refactorizarlos a un ámbito local más pequeño, especialmente si observa que algunas variables estáticas dependen de otras.

Pero tiene razón, no hay forma de garantizar un orden particular de inicialización, por lo que si su corazón está puesto en ello, mantener la inicialización en una función, como usted mencionó, es probablemente la manera más simple.


Usted ha respondido su propia pregunta. El orden de inicialización estático no está definido, y la forma más elegante de hacerlo (mientras sigue haciendo la inicialización estática, es decir, no refactorizarlo completamente) es envolver la inicialización en una función.

Lea los elementos de preguntas frecuentes de C ++ a partir de https://isocpp.org/wiki/faq/ctors#static-init-order