Prima di C ++ 11, potevamo eseguire solo l'inizializzazione in classe su membri const statici di tipo integrale o enumerazione. Stroustrup ne discute nelle sue domande frequenti su C ++ , fornendo il seguente esempio:
class Y {
const int c3 = 7; // error: not static
static int c4 = 7; // error: not const
static const float c5 = 7; // error: not integral
};
E il seguente ragionamento:
Allora perché esistono queste restrizioni scomode? Una classe è tipicamente dichiarata in un file di intestazione e un file di intestazione è tipicamente incluso in molte unità di traduzione. Tuttavia, per evitare complicate regole del linker, C ++ richiede che ogni oggetto abbia una definizione univoca. Questa regola sarebbe infranta se C ++ consentisse la definizione in classe di entità che dovevano essere archiviate in memoria come oggetti.
Tuttavia, C ++ 11 attenua queste restrizioni, consentendo l'inizializzazione in classe di membri non statici (§12.6.2 / 8):
In un costruttore non delegante, se un dato membro di dati non statici o una classe base non è designato da un mem-initializer-id (incluso il caso in cui non esiste un mem-initializer-list perché il costruttore non ha ctor-initializer ) e l'entità non è una classe base virtuale di una classe astratta (10.4), quindi
- se l'entità è un membro dati non statico che ha un inizializzatore di parentesi graffa o uguale , l'entità viene inizializzata come specificato in 8.5;
- altrimenti, se l'entità è un membro variante (9.5), non viene eseguita alcuna inizializzazione;
- altrimenti, l'entità è inizializzata per default (8.5).
La sezione 9.4.2 consente anche l'inizializzazione in classe di membri statici non const se sono contrassegnati con lo constexpr
specificatore.
Quindi cosa è successo alle ragioni delle restrizioni che avevamo in C ++ 03? Accettiamo semplicemente le "regole complicate del linker" o è cambiato qualcos'altro che lo rende più facile da implementare?