2010-03-10 10 views
135

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

+14

Sorpreso questo è un CW - questa realtà non hanno una risposta giusta, non è soggettiva, non è un argomento di discussione . –

+0

Sì, questa è una sentenza strana. Perché è stato spostato in CW? –

+1

Dato che OP è un nuovo utente, credo che abbia fatto un errore. – Gorpik

risposta

1

Come per la standard, a meno che non si inizializza esplicitamente nella lista di inizializzazione

+2

Bene, non è possibile specificare nulla nel costruttore predefinito * creato dal compilatore * – Gorpik

+2

@Gorpik - Punto preso ... ma se dico inizializzare esplicitamente, voglio dire che si deve fornire esplicitamente il costruttore predefinito – mukeshkumar

+0

@hype: I lo so, ma OP ha specificato che stava parlando del costruttore predefinito creato dal computer, non di quello che fornisci tu stesso. – Gorpik

-6

No. Il costruttore di default alloca la memoria e chiama il costruttore senza argomenti di tutti i genitori.

+5

E il costruttore no-arg di tutti i membri non POD. –

+0

Il costruttore alloca la memoria oppure il compilatore "assegna" la memoria per l'istanza e quindi richiama il costruttore? – visitor

+4

Questa risposta è abbastanza errata ... 1/Il Costruttore non assegna alcuna memoria, la inizializza. 2/La domanda riguardava il built-in e questa risposta riguarda le classi genitore ... come mai questa risposta off-topic sbagliata ha ottenuto 8 voti? –

-3

Tecnicamente li inizializza, utilizzando il costruttore predefinito, che per inciso non fa altro che allocare la memoria per essi.

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

+3

constrctor non assegna memoria. Il costruttore viene eseguito dopo l'allocazione della memoria. Per favore correggimi se ho torto. – ZoomIn

1

Come i precedenti oratori hanno dichiarato - no, non sono inizializzati.

Questa è in realtà una fonte di errori davvero strani in quanto i sistemi operativi moderni tendono a riempire le regioni di memoria appena allocate con zero. Se ti aspetti, potrebbe funzionare la prima volta. Tuttavia, man mano che l'applicazione continua a funzionare, gli oggetti delete -ing e new -ing, prima o poi finiscono in una situazione in cui ci si aspetta zero, ma si trova un avanzo diverso da zero da un oggetto precedente.

Quindi, perché è questo allora, non tutti i dati di new -ed sono stati assegnati nuovamente? 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 di una parola, qui tre byte ciascuna, vengono gestite in uyserspace e quindi non azzerate.

PS. Ho scritto "tendono a", cioè non puoi nemmeno contare sul successo la prima volta ...

16

Per tutti gli scopi pratici - no.


Tuttavia per le implementazioni che sono tecnicamente compatibili con lo standard C++, la risposta è che dipende se l'oggetto è POD o meno e su come si inizializza esso. Secondo la norma 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 in modo da non ne fanno uso.


Le parti rilevanti della norma sono la sezione 8.5.5 e 8.5.7

+0

E i globali, non sono sempre inizializzati a zero? – fredoverflow

+1

Per tutti tranne i primi, non viene chiamato il costruttore predefinito. In effetti, i loro cori predefiniti fanno lo stesso (non inizializzano nulla) - dopotutto sono tutti della stessa classe. Nel quarto, il valore del compilatore inizializza il POD e non chiama il costruttore predefinito. –

+0

@FredOverflow, tutto lo spazio dei nomi e gli oggetti statici locali o di classe sono inizializzati a zero, indipendentemente dal loro tipo (potrebbero essere le classi più complesse là fuori - tuttavia saranno inizializzati a zero). –

10

Io non sono assolutamente certo quello che vuoi dire, ma:

struct A { int x; }; 

int a; // a is initialized to 0 
A b; // b.x is initialized to 0 

int main() { 
    int c;   // c is not initialized 
    int d = int(); // d is initialized to 0 

    A e;   // e.x is not initialized 
    A f = A();  // f.x is initialized to 0 
} 

In ogni caso dove ho dì "non inizializzato" - potresti scoprire che il tuo compilatore fornisce un valore coerente, ma lo standard non lo richiede.

Un sacco di mano-ondeggiamento viene gettato in giro, anche da parte mia, su come i tipi predefiniti "in effetti" 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.

135

Definito implicitamente (dal compilatore) il costruttore predefinito di una classe non inizializza i membri dei tipi predefiniti.

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

Ad esempio, è diffusa l'errata convinzione che per la classe C la sintassi C() invoca sempre il costruttore predefinito. In realtà, tuttavia, la sintassi C() esegue la cosiddetta inizializzazione del valore dell'istanza della classe. Richiama il costruttore predefinito solo se è dichiarato dall'utente. (Questo è in C++ 03. In C++ 98 - solo se la classe non è POD). Se la classe non ha un costruttore dichiarato dall'utente, lo 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 classe. Per i tipi integrati risulta un'inizializzazione zero.

Ad esempio, se la classe non ha dall'utente dichiarato costruttore

class C { 
    int x; 
}; 

poi il compilatore implicitamente fornirne una. Il costruttore compilatore fornito non fa nulla, il che significa che non verrà inizializzato C::x

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

Tuttavia, i seguenti inizializzazioni saranno zero inizializzare x perché usano l'esplicito () inizializzatore

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

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

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

Un altro esempio di inizializzazione che viene eseguita senza coinvolgere costruttore è, naturalmente, l'inizializzazione aggregata

C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11. 
assert(c.x == 0); 

C d{}; // C++11 style aggregate initialization. 
assert(d.x == 0); 
+4

NOTA! Come per http://stackoverflow.com/a/3931589/18775 c'è un bug nel compilatore di Visual Studio C++ e in C c = C(); potrebbe non funzionare sempre –

+13

In C++ 11: 'C c {}' inizializza 'x' con' 0'? – towi

+0

Perché il compilatore mi avvisa che 'tm compleanno {0,0,0, t, m-1, j-1900};' sulle inizializzazioni mancanti. Raccolgo g ++ - 4.8 con * "inizializzatore mancante per il membro 'tm_yday'" che il valore è lasciato unitializzato - e non valore valore inizializzato con 0. Sarà un '=' prima che sia '{' un rimedio? – towi

Problemi correlati