Come fare statica de-inizializzazione se il distruttore ha effetti collaterali e l'oggetto si accede dal distruttore di un altro oggetto statico?

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

Domanda

È semplice e noto schema di evitare il fiasco inizializzazione statico, descritto in sezione 10.13 del C ++ FAQ Lite .

In questo schema standard, v'è un compromesso realizzato dal fatto che sia l'oggetto costruito viene mai distrutto (che non è un problema se il distruttore non ha importanti effetti collaterali) o l'oggetto statico non può tranquillamente essere letta da un'altra distruttore di oggetto statico (vedi sezione 10.14 del C ++ FAQ Lite ).

Quindi la mia domanda è: come si fa a evitare la statica de-inizializzazione fiasco se distruttore di un oggetto statico ha importanti effetti collaterali che alla fine devono verificarsi e l'oggetto statico deve essere accessibile da distruttore di un altro oggetto statico ?


(Nota: la FAQ-lite menziona tale questione venga risolta in FAQ 16.17 di C ++ FAQs: Domande frequenti di M. Cline e e G. Lomow non ho accesso a questo libro, che è. il motivo per cui chiedo a questa domanda, invece.)

È stato utile?

Soluzione

oggetti statici funzionali come oggetti globali sono garantiti per essere distrutti (ammesso che sono creati).

L'ordine di distruzione è l'inverso della creazione.
Così se un oggetto dipende da un altro oggetto durante la distruzione si deve garantire che sia ancora disponibile. Questo è relativamente semplice come è possibile forzare l'ordine di distruzione assicurandosi l'ordine della creazione è stato fatto correttamente.

Il seguente link è di circa singeltons ma descrive una situazione simile e la sua soluzione:
Finding C ++ problemi di ordine di inizializzazione statico

Estrapolando al caso generale di variabili globali inizializzati pigri come descritto nella FAQ lite possiamo risolvere il problema in questo modo:

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;
    }
}

Altri suggerimenti

Finché distruttore statica dell'altro oggetto viene eseguito prima, sei ok. È possibile assicurare questo avendo l'altro oggetto ottenere costruito prima di "oggetto A". Fintanto che entrambi gli oggetti vengono dichiarati nella stessa unità di compilazione, saranno inizializzati nell'ordine in cui appaiono nella sorgente, e distrutti nell'ordine opposto.

Se è necessario che questo accada attraverso unità di compilazione, sei fuori di fortuna. Meglio è quello di creare in modo dinamico in fase di esecuzione e distruggerli al termine della principale, piuttosto che facendoli statica.

E 'un po' di hack ma vorrei aggiungere alcuni Caccio statici per tenere traccia dell'ordine di de l'inizializzazione Poi l'oggetto che finisce ultima fa l'alto pulito anche se non è il proprietario.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top