Perché può esserci un inizializzatore nella definizione della classe?
quanto riguarda le due eccezioni per const
e constexpr
membri dati statici:
[class.static.data]/3
[Nota: In entrambi questi casi, l'elemento può apparire in espressioni costanti . - end note]
I.e. con un inizializzatore, puoi usarli in espressioni costanti, ad es.
struct s
{
static std::size_t const len = 10;
int arr[len];
};
std::size_t const s::len;
Se len
non è stata inizializzata nella definizione della classe, il compilatore non poteva facilmente conoscere il suo valore nella riga successiva per definire la lunghezza di arr
.
Si potrebbe discutere consentendo inizializzatori per dei non const
, non constexpr
membri dati statici nella definizione della classe, ma questo potrebbe interferire con l'ordine di inizializzazione:
[basic.start.init]/2
Le definizioni di membri di dati statici di modelli di classe esplicitamente specializzati hanno ordinato l'inizializzazione. Altri membri di dati statici di modelli di classe (ovvero specializzazioni istanziate in modo implicito o esplicito) hanno un'inizializzazione non ordinata. Altre variabili non locali con durata di archiviazione statica hanno ordinato l'inizializzazione.
Cioè, l'ordine delle definizioni inclusi gli inizializzatori è importante. L'ordine di inizializzazione (dinamica) di oggetti non locali è definito solo all'interno di un'unità di traduzione, questo è un altro motivo per cui deve esserci una definizione che include l'inizializzatore per i membri di dati statici non , non constexpr
.
Qual è il punto di questa definizione aggiuntiva?
Questo è già stato risposto nei commenti IMO. È possibile aggiungere l'ODR, ovvero come nome con collegamento esterno, il membro dei dati statici deve (solo) essere definito in un'unità di traduzione (se è utilizzato ODR). Spetta al programmatore scegliere questa unità di traduzione.
Il punto chiave è se la variabile sarà o meno utilizzata. Finché non lo è, in realtà non è necessario definirlo, poiché è sufficiente incollare il suo * valore * ogni volta che si fa riferimento alla variabile. –
Non è una definizione ** extra **; è una definizione. All'interno del corpo della classe hai una ** dichiarazione **. –
Come si potrebbe desiderare di accedere al membro dei dati statici da diverse unità di traduzione (= file cpp), sarà necessario definire una "posizione" a cui fa riferimento ogni unità di traduzione, cioè una singola unità di traduzione in cui è definito il membro statico. È la stessa cosa delle variabili extern (globali). – dyp