2014-10-03 16 views
24

La domanda di superamento è: come può un programmatore assicurarsi che le sue variabili statiche non locali siano inizializzate tramite l'inizializzazione statica e non tramite l'inizializzazione dinamica?Garantire l'inizializzazione statica (costante) di oggetti statici

Man mano che l'inizializzazione zero viene eseguita, occorre osservare l'inizializzazione costante.

3.6.2.2 Un inizializzatore costante per un oggetto o è un'espressione che è un'espressione costante, eccetto che può invocare constexpr costruttori per O e gli oggetti secondari anche se tali oggetti sono di classe non letterale tipi [Nota: una classe di questo tipo può avere un distruttore -end non valido -end]. inizializzazione costante viene eseguita:

- se ogni full-espressione (con conversioni implicite) che appare nella inizializzatore di riferimento con durata di conservazione statica o filo è un'espressione costante (5.19) e il riferimento è destinata a un lvalue che designa un oggetto con durata di memorizzazione statica o temporaneo (vedere 12.2);

- se un oggetto con durata di conservazione statica o filo è inizializzato da una chiamata di un costruttore, e se l'inizializzazione completa espressione è una costante inizializzatore per l'oggetto;

- se un oggetto con durata di conservazione statica o filo è non inizializzato da una chiamata costruttore e se l'oggetto è valore inizializzato o ogni full-espressione che appare nella sua inizializzatore è un'espressione costante.

Ho omesso il riferimento in quanto non è importante nel mio caso. Come ho capisco lo standard è che ci sono 3 casi:

  1. ctor
  2. no-ctor e l'inizializzazione del valore
  3. no-ctor e l'espressione costante

Diciamo che ho un seguente classe:

struct X { 
    bool flag = false; 
    // = {} will break VS2013 CTP so in that case use the 
    // regular ctor, which sadly still can't be declared constexpr 
    std::aligned_storage<sizeof(int), alignof(int)>::type storage = {}; 
}; 

Per quanto posso dire questa classe è p validamente valido per l'inizializzazione costante (ogni elemento può essere costantemente inizializzato). È vero?

Questa classe richiede un costruttore constexpr?

L'inizializzazione costante è garantita per C++ 11 e C++ 98?

Domanda laterale: quando verrà eseguita l'inizializzazione statica in caso di so/dll? Durante il tempo di caricamento, o potrebbe essere ritardato ulteriormente?

+0

Nota che c'è molta garanzia, questa mi sembra specifica per l'implementazione. Per quanto riguarda la domanda laterale (* quando *) dipenderà. Può effettivamente essere fatto * al tempo di collegamento * nel caso di costanti che vivono nel segmento '.bss' (formato ELF) o può richiedere di attendere il tempo di caricamento per le costanti inizializzate con un indirizzo di funzione (perché dipende da dove è quella funzione mappato in memoria). Potrei perfettamente immaginare che venga fatto pigramente al primo accesso. Questo è * molto * specifico per l'implementazione. –

+0

'X x;' viene inizializzato di default, il che implica una chiamata al costruttore. È interessante notare che * non esiste espressione *. Il costruttore predefinito non è 'constexpr', poiché' storage' non è inizializzato (è garantito che sia un POD dopo aver aggiunto ':: type'). Inoltre, il responsabile di un oggetto 'const' inizializzato di default deve essere fornito dall'utente. – dyp

+0

@dyp Non ho notato il ': type' thingy - risolto ora (ha senso usare il modulo non-type?). Ho ragione di ritenere che l'esistenza di POD sia "constexpr"? –

risposta

1

Sarebbe utile conoscere lo scopo di questa domanda. E anche se la tua preoccupazione è l'allocazione o l'inizializzazione specifica.

Tuttavia, il tipo di inizializzazione non dovrebbe avere importanza perché lo spazio richiesto è allocato in fase di compilazione. A seconda di come si definisce la variabile, finirà nella sezione .bss o .data.

L'inizializzazione, come sapete, serve solo a garantire un contenuto specifico nella memoria prima che venga utilizzato per la prima volta. Se non si definisce un costruttore che alloca la memoria dinamica, non ci sarà alcuna allocazione dinamica (se questa è la tua preoccupazione).

Per i costruttori semplici, credo che il compilatore genererà il codice inline e userà lo stesso per inizializzare l'oggetto in fase di compilazione (non sono sicuro di cosa lo standard parli della stessa ma è possibile che dipenda dalla catena di strumenti.) Con i costruttori complessi, gli oggetti statici non locali verranno inizializzati quando l'immagine viene caricata in memoria e gli oggetti statici locali verranno inizializzati quando viene caricato lo stack frame. In ogni caso dovresti trovare l'oggetto in uno stato noto prima del primo utilizzo.

1

Domanda laterale: quando verrà eseguita l'inizializzazione statica in caso di so/dll? Durante il tempo di caricamento, o potrebbe essere ritardato ulteriormente?

In Windows, inizializzazione statico avviene prima prima DllMain() viene richiamato con caricatore DLL serratura acquisita. Questo limita fortemente ciò che puoi fare nei costruttori per i tuoi oggetti statici. Non è possibile caricare altre DLL (LoadLibrary) o chiamare qualsiasi altra funzione che POTREBBE causare il caricamento di una DLL, il che esclude qualsiasi cosa oltre la semplice inizializzazione e le funzioni esportate da Kernel32.

Vedere gli ultimi paragrafi dei documenti DllMain (MSDN) per i dettagli.

Problemi correlati