tutorial que programacion orientada objetos objeto herencia ejemplos constructores codigo clases c++ static destruction

que - Orden de destrucción de objetos estáticos en C++



que es un objeto en c++ (9)

¿Puedo controlar el orden en que se destruyen los objetos estáticos? ¿Hay alguna forma de hacer cumplir mi orden deseada? Por ejemplo, ¿para especificar de alguna manera que me gustaría que un determinado objeto se destruyera por última vez, o al menos después de otro objeto estático?


¿Realmente necesitas la variable para inicializar antes de main ?

Si no lo haces, puedes usar un simple modismo para controlar realmente el orden de construcción y destrucción con facilidad, mira aquí:

#include <cassert> class single { static single* instance; public: static single& get_instance() { assert(instance != 0); return *instance; } single() // : normal constructor here { assert(instance == 0); instance = this; } ~single() { // normal destructor here instance = 0; } }; single* single::instance = 0; int real_main(int argc, char** argv) { //real program here... //everywhere you need single::get_instance(); return 0; } int main(int argc, char** argv) { single a; // other classes made with the same pattern // since they are auto variables the order of construction // and destruction is well defined. return real_main(argc, argv); }

NO DETIENE que trates de crear una segunda instancia de la clase, pero si lo haces, la afirmación fallará. En mi experiencia, funciona bien.


Las otras respuestas a esto insisten en que no se puede hacer. Y tienen razón, de acuerdo con la especificación, pero hay un truco que te permitirá hacerlo.

Cree solo una sola variable estática, de una clase o estructura que contenga todas las demás cosas que normalmente haría variables estáticas, como por ejemplo:

class StaticVariables { public: StaticVariables(): pvar1(new Var1Type), pvar2(new Var2Type) { }; ~StaticVariables(); Var1Type *pvar1; Var2Type *pvar2; }; static StaticVariables svars;

Puedes crear las variables en el orden que necesites y, lo que es más importante, destruirlas en el orden que necesites, en el constructor y el destructor para StaticVariables . Para que esto sea completamente transparente, puede crear referencias estáticas a las variables también, de esta forma:

static Var1Type &var1(*svars.var1);

Voilà - control total. :-) Dicho esto, esto es trabajo extra, y generalmente innecesario. Pero cuando es necesario, es muy útil saberlo.



Los objetos estáticos se destruyen en el orden inverso al que están construidos (p. Ej., El primer objeto construido se destruye por última vez), y se puede controlar la secuencia en la que se construyen los objetos estáticos, utilizando la técnica descrita en el Ítem 47, " Asegúrese de que los objetos globales se inicialicen antes de que se usen " en el libro de Meyers Effective C ++ .

Por ejemplo, para especificar de algún modo que me gustaría que un determinado objeto se destruyera por última vez, o al menos después de otro onject estático?

Asegúrese de que esté construido antes que el otro objeto estático.

¿Cómo puedo controlar la orden de construcción? no todas las estáticas están en el mismo dll.

Ignoraré (por simplicidad) el hecho de que no están en la misma DLL.

Mi paráfrasis del ítem 47 de Meyers (que tiene 4 páginas) es la siguiente. Suponiendo que global está definido en un archivo de encabezado como este ...

//GlobalA.h extern GlobalA globalA; //declare a global

... agrega un código para que incluya un archivo como este ...

//GlobalA.h extern GlobalA globalA; //declare a global class InitA { static int refCount; public: InitA(); ~InitA(); }; static InitA initA;

El efecto de esto será que cualquier archivo que incluya GlobalA.h (por ejemplo, su archivo fuente GlobalB.cpp que define su segunda variable global) definirá una instancia estática de la clase InitA, que se construirá antes que cualquier otra cosa en ese archivo fuente (por ejemplo, antes de su segunda variable global).

Esta clase InitA tiene un contador de referencia estático. Cuando se construye la primera instancia de InitA, que ahora está garantizado antes de que se construya su instancia de GlobalB, el constructor de InitA puede hacer lo que tenga que hacer para garantizar que la instancia globalA se inicialice.


Los objetos estáticos se destruyen en el orden inverso de construcción. Y el orden de construcción es muy difícil de controlar. Lo único de lo que puede estar seguro es que dos objetos definidos en la misma unidad de compilación se construirán en el orden de definición. Cualquier otra cosa es más o menos aleatorio.


No hay forma de hacerlo en C ++ estándar, pero si tiene un buen conocimiento práctico de su compilador interno específico, probablemente se pueda lograr.

En Visual C ++ los punteros a las funciones estáticas init se ubican en el segmento .CRT$XI (para el tipo estático init C) o el segmento .CRT$XC (para el inicio estático tipo C ++) El enlazador recopila todas las declaraciones y las combina alfabéticamente. Puede controlar el orden en que se produce la inicialización estática declarando sus objetos en el segmento apropiado usando

#pragma init_seg

por ejemplo, si desea que los objetos del archivo A se creen antes del archivo B:

Archivo A.cpp:

#pragma init_seg(".CRT$XCB") class A{}A;

Archivo B.cpp:

#pragma init_seg(".CRT$XCC") class B{}B;

.CRT$XCB se fusiona antes de .CRT$XCC . Cuando el CRT itera a través de los punteros de la función de inicio estático, encontrará el archivo A antes del archivo B.

En Watcom, el segmento es XI y las variaciones en #pragma initialize pueden controlar la construcción:

#pragma initialize before library #pragma initialize after library #pragma initialize before user

... ver documentación para más


No, no puedes. Nunca debe confiar en la otra construcción / destrucción de objetos estáticos.

Siempre puede usar un singleton para controlar el orden de construcción / destrucción de sus recursos globales.


Puede lograr efectivamente una funcionalidad similar al tener un static std::optional<T> lugar de un T Solo inicialízalo como lo harías con una variable, std::nullopt con indirección y destrúyela asignando std::nullopt (o, para boost, boost::none ).

Es diferente de tener un puntero ya que tiene memoria preasignada, que supongo que es lo que quieres. Por lo tanto, si lo destruye y (tal vez mucho más tarde) lo recrea, su objeto tendrá la misma dirección (que puede conservar) y no pagará el costo de la asignación / desasignación dinámica en ese momento.

Utilice boost::optional<T> si no tiene std:: / std::experimental:: .


Respuesta corta: en general, no.

Respuesta un poco más larga: Para objetos estáticos globales en una sola unidad de traducción, el orden de inicialización es de arriba a abajo, el orden de destrucción es exactamente el inverso. El orden entre varias unidades de traducción no está definido.

Si realmente necesita un pedido específico, necesita hacerlo usted mismo.