2016-06-12 22 views
9

consideri il seguente, dove abbiamo due file di ambito oggetti in diverse unità di traduzione, che è la solita installazione per indefinita-comportamento attraverso il fiasco ordine di inizializzazione:Gli atomici con ambito file sono soggetti al fiasco dell'ordine di inizializzazione?

a.hpp:

struct thing { 
public: 
    thing(int value); 
    ~thing(); 

    int value() const; 

    static int count(); 

private: 
    int _value; 
}; 

a.cpp:

#include "a.hpp" 

#include <atomic> 

namespace { 
    std::atomic<int> things; 
} 

thing::thing(int value) : _value(value) { 
    ++things; 
} 

thing::~thing() { 
    --things; 
} 

int thing::value() const { 
    return _value; 
} 

int thing::count() { 
    return things.load(); 
} 

b.cpp:

#include <iostream> 

#include "a.hpp" 

namespace { 
    thing static_thing(42); 
} 

void foo() { 
    std::cout << static_thing.value() << ' ' << thing::count() << '\n'; 
} 

È questo il codice di un ordine di fiasco di inizializzazione tra il file ambito atomica things in a.cpp e il file ambito static_thing in b.cpp? Se no, perché no? In particolare, cosa rende speciale std :: atomic che rimuove quello che altrimenti sarebbe un chiaro fiasco di ordine init? C'è un particolare concetto che può essere chiamato per far rispettare questo con un asser statico? Qualcosa di simile:

static_assert(std::is_trivial<decltype(things)>::value, "file static counter is not trivial"); 

caso contrario std::is_trivial, c'è un altro concetto e il tipo di caratteristica associata che modelli migliori questo?

Al contrario, esiste un fiasco di inizializzazione? Stesse domande su se sì, perché, o perché no.

+0

mia breve ricerca in materia suggeriscono che data la garanzia che 'std :: atomica ' devono essere specializzati, e atomiche specializzati hanno determinate proprietà, 'std :: atomica ' sarebbe proprio come un POD, per l'inizializzazione ordine, ad es nessun fiasco. Tuttavia, questo caso può anche essere risolto proprio come la maggior parte degli altri casi soggetti a init fiasco: ma dichiarando gli oggetti statici in ambito statico della funzione e sfruttando il fatto che gli oggetti con scope statica devono essere inizializzati prima della prima entrata in la funzione. –

+2

L'ordine di costruzione di oggetti statici in traduzione diversa non è ancora specificato. L'uso di 'std :: atomic' non lo cambia. Perché ti aspetti che succeda? I compilatori particolari possono creare un'istanza per prima cosa sull'atomica, ma non è necessario. – Peter

+0

@Peter perché std :: atomic ha un costruttore constexpr e viene inizializzato con una costante e ha un distruttore banale. Questo suggerisce che l'oggetto è effettivamente immortale. Poiché l'init statico ha luogo prima di qualsiasi init dinamico, e poiché non c'è nulla da fare per distruggerlo, è fondamentalmente immortale. Non vedo come possa esserci un ordine di inizializzazione fiasco w.r.t. qualsiasi cosa con inizializzazione dinamica. – acm

risposta

1

La mia conoscenza del "fiasco dell'ordine di inizializzazione" di C++ è che si applica solo quando è necessario chiamare i costruttori in fase di runtime. Se il codice può declinare nell'inizializzazione di una posizione di memoria su un valore fisso, tale valore viene inserito nella sezione del linker "dati inizializzati" (.data) come ogni altro POD preinizializzato (Plain Ol 'Data), e lì non è un fiasco.

Suggerirei che uno atomic soddisfi questo stesso criterio.

2

std::atomic<> è un tipo di layout standard con costruttori di base banali e distruttori banali. Pertanto, viene inizializzato nella fase di inizializzazione statica , prima della fase di inizializzazione dinamica quando vengono richiamati i costruttori di oggetti globali.

In altre parole, nessun fiasco dell'ordine di inizializzazione si verifica qui.

Poiché non si inizializza esplicitamente lo spazio dei nomi con ambito std::atomic<int>, verrà inizializzato a zero.

§ 3.6.2 Inizializzazione delle variabili non locali

variabili con durata statica stoccaggio (3.7.1) o durata di conservazione filo (3.7.2) sono inizializzati a zero (8,5) prima di qualsiasi altra l'inizializzazione ha luogo.

Insieme, l'inizializzazione zero e l'inizializzazione costante sono chiamate inizializzazione statica; tutte le altre inizializzazioni sono l'inizializzazione dinamica. L'inizializzazione statica deve essere eseguita prima di qualsiasi inizializzazione dinamica.

+0

Questo è corretto bug del compilatore di moduli (Vedi [questo] (https://developercommunity.visualstudio.com/content/problem/76198/vs-2017-compiler- creates-broken-debug-build-using.html) che riguarda VS 2017 15.3) – Arnaud

Problemi correlati