2016-06-08 12 views
22

Sembra che possiamo utilizzare in modo sicuro l'oggetto std::cout nei costruttori di oggetti con durata di archiviazione statica come indicato in questo question.Modelli variabili e std :: cout - ordine di costruzione

Tuttavia, non sono del tutto sicuro che possiamo tranquillamente utilizzare in caso di modelli variabili:

#include <iostream> 

template<class T> 
T x = T{}; 

void foo() 
{ 
    class Test 
    { 
    public: 
     Test() { std::cout << "Test::Test\n"; } 
    }; 

    Test t = x<Test>; 
} 


int main() 
{ 
    std::cout << "main\n"; 
} 

crash questo codice in clang (live example) e non sono sicuro che si tratti di un bug o non.

+0

Funziona con GCC. Forse è un bug in clang? – Cornstalks

+2

@Cornstalks Forse. Ma forse è solo un comportamento non specificato? – FrozenHeart

risposta

21

Come spiegato in questa domanda, un effetto di

#include <iostream> 

è l'equivalente di definire una variabile globale

static std::ios_base::Init __init; 

che (supponendo che si include all'inizio del TU) garanzie che per tutti gli oggetti di durata di archiviazione statica con ordinati nell'inizializzazione nella stessa TU, gli oggetti di flusso sono stati impostati.

specializzazioni template Tuttavia, esplicitamente e implicitamente esemplificati hanno ordinata inizializzazione ([basic.start.dynamic]/1) :

inizializzazione dinamica di una variabile non locale con statico stoccaggio durata è ordinata se la variabile è un implicitamente o esplicitamente specializzazione istanziata, e in caso contrario è ordinata [nota omessa]. Le variabili con inizializzazione ordinata definite all'interno di una singola unità di traduzione devono essere inizializzate nell'ordine delle loro definizioni nell'unità di traduzione.

E poiché

Se un programma viene avviato un thread, la successiva inizializzazione non ordinato di una variabile è non in sequenza rispetto ad ogni altra inizializzazione dinamica. In caso contrario, l'inizializzazione non ordinata di una variabile è sequenzialmente indeterminata rispetto ad ogni altra inizializzazione dinamica .

non c'è alcuna garanzia che gli oggetti stream sono stati inizializzati al momento il modello di specializzazione variabile x<Test> viene inizializzata.

In questo caso, poiché una delle possibili esecuzioni risulta in un comportamento non definito (utilizzando gli oggetti flusso prima che siano inizializzati), il comportamento dell'intero programma non è definito (vedere [intro.execution]/5).

La correzione è quello di costruire un oggetto std::ios_base::Init te stesso nel costruttore Test s'.


Questo è in realtà underspecified per i modelli di variabili quando C++ 14 è stato pubblicato, ma è sempre stato l'intento.

+0

Quindi hanno un'inizializzazione non ordinata anche per quegli oggetti che sono definiti nella stessa unità di traduzione? – FrozenHeart

+2

@FrozenHeart Sì. Non c'è comunque ordine tra le diverse TU. –

+0

Grazie mille. La prossima domanda quindi - http://stackoverflow.com/questions/37706549/stdcout-usage-in-constructors-of-objects-with-static-storage-duration – FrozenHeart

Problemi correlati