inizializzazione di array
-
06-07-2019 - |
Domanda
Sono abbastanza certo che le matrici di tipi predefiniti siano unitizzate, mentre le matrici di UDT sono inizializzate di default.
int foo [5]; // conterrà junk
Foo foo [5]; // conterrà 5 oggetti Foo inizializzati di default
Ciò si verifica indipendentemente dal fatto che l'array sia allocato nello stack o nell'heap.
Tuttavia, trovo difficile trovare una fonte autorevole su questo. Bjarne afferma che:
" I membri di matrici e strutture sono inizializzati di default o no a seconda che l'array o la struttura siano statici " che non mi dice molto.
Ho anche cercato di trovare qualcosa nello standard, ma finora nessun risultato è stato inutile.
Qualcuno conosce una fonte autorevole per confermare quanto sopra?
Soluzione
ISO C ++ 03 è tanto autorevole quanto si ottiene:
Una POD-struct è una classe aggregata che non ha membri di dati non statici di tipo non-POD-struct, non-POD-union (o array di tali tipi) o riferimento e non ha assegnazione di copia definita dall'utente operatore e nessun distruttore definito dall'utente. Allo stesso modo, un'unione POD è un'unione aggregata che non ha membri di dati non statici di tipo non-POD-struct, non-POD-union (o array di tali tipi) o riferimento e non ha un operatore di assegnazione della copia definito dall'utente e nessun distruttore definito dall'utente. Una classe POD è una classe che è una struttura POD o un'unione POD.
I tipi aritmetici (3.9.1), i tipi di enumerazione, i tipi di puntatore e i tipi di puntatore a membro (3.9.2) e le versioni qualificate per cv di questi tipi (3.9.3) sono chiamati collettivamente tipi scalari. I tipi scalari, i tipi di struttura POD, i tipi di unione POD (clausola 9), le matrici di tali tipi e le versioni qualificate in cv di questi tipi (3.9.3) sono collettivamente chiamati tipi POD.
Inizializzare a zero un oggetto di tipo T significa:
- se T è un tipo scalare (3.9), l'oggetto è impostato sul valore 0 (zero) convertito in T;
- se T è un tipo di classe non sindacale, ciascun membro di dati non statico e ogni classe di base subobject è a zero inizializzato;
- se T è un tipo di unione, il primo membro di dati con nome dell'oggetto viene inizializzato con zero;
- se T è un tipo di array, ogni elemento è inizializzato con zero;
- se T è un tipo di riferimento, non viene eseguita alcuna inizializzazione.
Inizializzare per default un oggetto di tipo T significa:
- se T è un tipo di classe non POD (clausola 9), viene chiamato il costruttore predefinito per T (e l'inizializzazione non è corretta se T non ha un costruttore predefinito accessibile);
- se T è un tipo di array, ogni elemento è inizializzato come predefinito;
- altrimenti, l'oggetto viene inizializzato con zero.
Inizializzare un oggetto di tipo T significa:
- se T è un tipo di classe (clausola 9) con un costruttore dichiarato dall'utente (12.1), viene chiamato il costruttore predefinito per T (e l'inizializzazione non è corretta se T non ha un costruttore predefinito accessibile);
- se T è un tipo di classe non sindacale senza un costruttore dichiarato dall'utente, allora ogni membro di dati non statico e componente di classe base di T è inizializzato dal valore;
- se T è un tipo di array, ogni elemento è inizializzato dal valore;
- altrimenti, l'oggetto viene inizializzato con zero
Ogni oggetto con durata di memorizzazione statica deve essere inizializzato a zero all'avvio del programma prima che avvenga qualsiasi altra inizializzazione. [Nota: in alcuni casi, l'inizializzazione aggiuntiva viene eseguita in seguito.]
Un oggetto il cui inizializzatore è un insieme vuoto di parentesi, ovvero (), deve essere inizializzato dal valore.
Se non viene specificato alcun inizializzatore per un oggetto e l'oggetto appartiene a un tipo di classe non POD (possibilmente qualificato in cv) (o array di questi), l'oggetto deve essere inizializzato per impostazione predefinita; se l'oggetto è di tipo const-qualificato, il tipo di classe sottostante deve avere un costruttore predefinito dichiarato dall'utente. Altrimenti, se non viene specificato alcun inizializzatore per un oggetto non statico, l'oggetto e gli eventuali oggetti secondari hanno un valore iniziale indeterminato); se l'oggetto o uno qualsiasi dei suoi oggetti secondari sono di tipo const-qualificato, il programma è mal formato.
Ad esempio, int
è sicuramente un tipo POD (è un tipo aritmetico) e quindi un campo locale o di tipo int
, in assenza di inizializzatore, avrà un valore indeterminato. Per Foo
, questo dipende da come viene definito - approssimativamente parlando, se non ha un costruttore e tutti i suoi membri sono di tipo POD, allora è esso stesso un tipo POD e nessuna inizializzazione avviene anche. Altrimenti, viene chiamato il costruttore predefinito. Anche allora, ciò non significa che membri siano inizializzati - le regole sono ricorsive, quindi i membri POD di tipo non-POD non saranno inizializzati a meno che il costruttore di quel tipo non lo faccia specificamente (nel suo inizializzatore lista).
Le variabili e i campi statici saranno in ogni caso inizializzati con zero. Si noti che ciò vale anche per i non-POD, il che significa che una variabile statica di un tipo di classe garantisce che tutti i campi siano ricorsivamente impostati su (T) 0
anche prima dell'esecuzione del costruttore.
Un trucco utile per inizializzare in modo predefinito qualsiasi tipo POD aggregato consiste nell'utilizzare {}
nell'inizializzatore; si noti che funziona sia con le strutture che con le matrici:
char s[10] = {}; // all elements default-initialized
Foo foo = {}; // all fields recursively default-initialized
Altri suggerimenti
Dice nello standard C ++, in 8.5.9:
Se non viene specificato alcun inizializzatore per un oggetto e l'oggetto è (possibilmente tipo di classe POD non qualificato cv (o matrice di ciò), l'oggetto deve essere default-inizializzato; se l'oggetto lo è di tipo qualificato, il il tipo di classe sottostante deve avere a costruttore predefinito dichiarato dall'utente. Altrimenti, se non c'è inizializzatore specificato per un oggetto non statico, il oggetto e relativi oggetti secondari, se presenti, hanno un valore iniziale indeterminato.
" I membri di matrici e strutture sono inizializzati di default o no a seconda che l'array o la struttura siano statici "
Questo è autorevole, anche se potrebbe essere più chiaro:
- Le matrici e le strutture dichiarate come
static
sono inizializzate su zero. - Gli array e le strutture locali di tipi predefiniti ( cioè che non hanno costruttori) non sono inizializzati.