Il costruttore predefinito inizializza i tipi built-in?

Il costruttore predefinito (creato dal compilatore) inizializza i tipi built-in?

Il costruttore predefinito di una class definita in modo implicito (dal compilatore) non inizializza i membri dei tipi predefiniti.

Tuttavia, è necessario tenere presente che in alcuni casi l’inizializzazione di un’istanza della class può essere eseguita in altri modi. Costruttore non predefinito, per niente costruttore.

Ad esempio, c’è una credenza errata diffusa che per la class C la syntax C() invoca sempre il costruttore predefinito. In realtà, tuttavia, la syntax C() esegue la cosiddetta inizializzazione del valore dell’istanza della class. Richiama solo il costruttore predefinito se è dichiarato dall’utente . (Questo è in C ++ 03. In C ++ 98 – solo se la class non è POD). Se la class non ha un costruttore dichiarato dall’utente, la C() non chiamerà il costruttore predefinito fornito dal compilatore, ma eseguirà piuttosto un tipo speciale di inizializzazione che non coinvolge affatto il costruttore di C Invece, valuterà direttamente-inizializza ogni membro della class. Per i tipi integrati risulta un’inizializzazione zero.

Ad esempio, se la tua class non ha un costruttore dichiarato dall’utente

 class C { int x; }; 

quindi il compilatore ne fornirà implicitamente uno. Il costruttore fornito dal compilatore non farà nulla, il che significa che non inizializzerà C::x

 C c; // Compiler-provided default constructor is used // Here `cx` contains garbage 

Tuttavia, le seguenti inizializzazioni inizializzeranno a zero x perché usano l’inizializzatore esplicito ()

 C c = C(); // Does not use default constructor for `C()` part // Uses value-initialization feature instead assert(cx == 0); C *pc = new C(); // Does not use default constructor for `C()` part // Uses value-initialization feature instead assert(pc->x == 0); 

Il comportamento di () initializer è diverso sotto alcuni aspetti tra C ++ 98 e C ++ 03, ma non in questo caso. Per la class C cui sopra sarà lo stesso: () inizializzatore esegue l’inizializzazione zero di C::x .

Un altro esempio di inizializzazione che viene eseguito senza coinvolgere il costruttore è, naturalmente, l’inizializzazione di aggregazione

 C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11. assert(cx == 0); C d{}; // C++11 style aggregate initialization. assert(dx == 0); 

Per tutti gli scopi pratici – no.


Tuttavia, per le implementazioni tecnicamente conformi allo standard C ++, la risposta è che dipende se l’object è POD o meno e su come lo si inizializza. Secondo lo standard C ++:

 MyNonPodClass instance1;//built in members will not be initialized MyPodClass instance2;//built in members will be not be initialized MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized 

Tuttavia, nel mondo reale, questo non è ben supportato quindi non usarlo.


Le parti rilevanti dello standard sono le sezioni 8.5.5 e 8.5.7

Non sono abbastanza sicuro di cosa intendi, ma:

 struct A { int x; }; int a; // a is initialized to 0 A b; // bx is initialized to 0 int main() { int c; // c is not initialized int d = int(); // d is initialized to 0 A e; // ex is not initialized A f = A(); // fx is initialized to 0 } 

In ogni caso in cui dico “non inizializzato”, potresti scoprire che il tuo compilatore fornisce un valore coerente, ma lo standard non lo richiede.

Un sacco di ondeggiamenti a mano vengono lanciati, incluso da me, su come i “tipi” built-in hanno un costruttore predefinito. In realtà l’inizializzazione predefinita e l’inizializzazione del valore sono termini definiti nello standard, che personalmente devo cercare ogni volta. Solo le classi sono definite nello standard per avere un costruttore implicito predefinito.

Secondo lo standard, non a meno che non si inizializzi esplicitamente nell’elenco di inizializzazione

Come hanno affermato i precedenti oratori, no, non sono inizializzati.

Questo è in realtà una fonte di errori davvero strani in quanto i moderni SO tendono a riempire aree di memoria appena allocate con zero. Se ti aspetti, potrebbe funzionare la prima volta. Tuttavia, man mano che la tua applicazione continua a funzionare, delete -ing e new -ing oggetti, prima o poi finirai in una situazione in cui ti aspetti zero, ma si trova un avanzo diverso da zero da un object precedente.

Quindi, perché è questo allora, non tutti i dati nuovi sono stati allocati di recente? Sì, ma non sempre dal sistema operativo. Il sistema operativo tende a funzionare con blocchi di memoria più grandi (ad esempio 4 MB alla volta), quindi tutte le allocazioni e le allocazioni minuscole word-here-three-bytes-there vengono gestite in uyserspace e quindi non azzerate.

PS. Ho scritto “tend to to”, cioè non puoi nemmeno contare sul successo la prima volta …

Tecnicamente li inizializza, usando il costruttore di default, che per inciso non fa altro che allocare la memoria per loro.

Se quello che volevi sapere è se sono impostati o meno su qualcosa di sano come 0 per int s, allora la risposta è “no”.

No. Il costruttore predefinito assegna la memoria e chiama il costruttore senza argomenti di qualsiasi genitore.