clang++
non consente mai default initialization of a const variable of class-type without a user-defined constructor; g++
è leggermente meno restrittivo (vedi sotto). Secondo this answer, questo è dovuto al fatto che i tipi di POD "non sono inizializzati di default." Se capisco correttamente, ciò significa che l'inizializzazione di default non richiama il costruttore di default, né invoca l'inizializzazione del valore, quindi i membri di dati all'interno del tipo POD non sono inizializzati. Ovviamente non ha senso avere un tipo const POD con valori non inizializzati, poiché possono mai essere inizializzati e quindi non sono sicuri da usare.Quando e come inizializzare di default una variabile const?
Ci sono alcune varianti di questa situazione:
- Il tipo è tecnicamente "POD", ma non contiene membri di dati (solo funzioni). (
clang++
non tratta questo come un caso speciale, né, credo, fa lo standard, mag++
LO PERMETTE, anche quando il costruttore è contrassegnatoexplicit
.) - Un costruttore vuoto è definita utilizzando
{}
. (Questa soluzione è consigliata nella paginaclang
che descrive il problema.) - Il costruttore predefinito è dichiarato
=default
. (C++ 11 in poi, il tipo è ancora considerato POD, quindi né il compilatore né lo standard trattano come un caso speciale.) - L'inizializzazione di aggregazione viene esplicitamente invocata utilizzando
{}
, che (se ho capito correttamente) diventa inizializzazione del valore . (C++ 11 in poi;. Entrambi i compilatori-e, credo, lo standard-lo permettono)
Nel primo caso, non ci possono essere non inizializzate membri, quindi è chiaro perché qualsiasi istanza della la classe stessa sarebbe mai considerata "non inizializzata", indipendentemente dal fatto che sia const
o meno. Dal momento che g++
consente questo comportamento, è sicuro da usare? Perché è vietato da clang++
e dallo standard? (E ci sono altri casi in cui g++
permette POD-default-inizializzazione dove clang++
non?)
Nel secondo e terzo caso, l'esigenza di utilizzare {}
invece di =default
sembra strano per me. MODIFICA:this question spiega abbastanza bene la differenza, quindi ho rimosso la parte della domanda chiedendo la distinzione. (Io continuo a pensare che sia un aspetto terribilmente confuso della lingua, però.)
Infine, sarà Foo f{}
sempre zero-inizializzare i membri di tipo built-in se Foo::Foo(void)
è {}
, =default
, o implicitamente dichiarata?
Esiste un caso d'uso per un tipo const POD senza variabili membro? Puoi anche usare uno non-const, poiché non ci sono membri che potrebbero essere erroneamente cambiati. –
@MattMcNabb Non ne sono sicuro. Questo è uno schema che ricorre ripetutamente nel codice di un collega, in funzioni di fabbrica (o ... qualcosa del genere). Cercherò di ricordare di chiedere a quel collega domani quale sia l'intento. –
Un costruttore definito con '{}' non è un costruttore banale. – 0x499602D2