Cómo hacer estática de-inicialización si el destructor tiene efectos secundarios y se accede al objeto del destructor de otro objeto estático?

StackOverflow https://stackoverflow.com/questions/3143180

Pregunta

Hay una simple y patrón bien conocido para evitar el fracaso de inicialización estática, se describe en sección 10.13 de la C ++ FAQ Lite .

En este patrón estándar, hay una compensación hecho en que, o bien el objeto construido nunca se destruido (que no es un problema si el destructor no tiene efectos secundarios importantes) o el objeto estático no se puede acceder de forma segura de otro destructor de objeto estático (ver 10.14 de la C ++ FAQ Lite ).

Así que mi pregunta es: ¿Cómo se puede evitar la estática de-inicialización fiasco si destructor de un objeto estático tiene importantes efectos secundarios que con el tiempo deben ocurrir y el objeto estático se debe acceder por destructor de otro objeto estático ?


(Nota: la AYUDA-lite menciona esta pregunta se responde en FAQ 16.17 de C ++ Preguntas frecuentes: Preguntas frecuentes por M. Cline y G. Lomow y no tengo acceso a este libro, que es. por eso hago esta pregunta en su lugar.)

¿Fue útil?

Solución

objetos estáticos funcionan como objetos globales están garantizados para ser destruido (suponiendo que se crean).

El orden de destrucción es la inversa de la creación.
Así, si un objeto depende de otro objeto durante la destrucción debe garantizar que todavía está disponible. Esto es relativamente simple como se puede forzar el orden de destrucción asegurándose de que el orden de la creación se hace correctamente.

En el siguiente enlace se trata singeltons sino que describe una situación similar y su solución:
Finding C ++ problemas de orden de inicialización estática

Al extrapolar al caso general de variables globales inicializadas perezosos como se describe en el FAQ Lite podemos resolver el problema como este:

namespace B
{
    class B { ... };

    B& getInstance_Bglob;
    {
        static B instance_Bglob;
        return instance_Bglob;;
    }

    B::~B()
    {
         A::getInstance_abc().doSomthing();
         // The object abc is accessed from the destructor.
         // Potential problem.
         // You must guarantee that abc is destroyed after this object.
         // To gurantee this you must make sure it is constructed first.
         // To do this just access the object from the constructor.
    }

    B::B()
    {
        A::getInstance_abc();
        // abc is now fully constructed.
        // This means it was constructed before this object.
        // This means it will be destroyed after this object.
        // This means it is safe to use from the destructor.
    }
}
namespace A
{
    class A { ... };

    A& getInstance_abc()
    {
        static A instance_abc;
        return instance_abc;
    }
}

Otros consejos

Mientras destructor estática del otro objeto se ejecuta en primer lugar, que estás bien. Usted puede asegurar esto haciendo que el otro objeto conseguir construido antes de que "el objeto A". Siempre que ambos objetos se declaran en la misma unidad de compilación, que serán inicializados en el orden en que aparecen en la fuente, y destruidos en el orden opuesto.

Si necesita que esto suceda a través de las unidades de compilación, estás de suerte. Mejor es crear de forma dinámica en tiempo de ejecución y destruirlos al final del principal, en lugar de hacerlos estática.

Es un poco de un truco, pero me gustaría añadir algunas Bools estáticas para realizar un seguimiento de la orden de inicialización de entonces el objeto de que termina la última hace la limpieza, incluso si no es el propietario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top