Cosa significano le seguenti frasi in C ++:
zero inizializzazione,
inizializzazione predefinita e
valore di inizializzazione
Cosa dovrebbe sapere uno sviluppatore C ++ su di loro?
Cosa significano le seguenti frasi in C ++:
zero inizializzazione,
inizializzazione predefinita e
valore di inizializzazione
Cosa dovrebbe sapere uno sviluppatore C ++ su di loro?
Risposte:
Una cosa da capire è che "l'inizializzazione del valore" è nuova con lo standard C ++ 2003 - non esiste nello standard originale del 1998 (penso che potrebbe essere l'unica differenza che è più di un chiarimento). Vedi la risposta di Kirill V. Lyadvinsky per le definizioni direttamente dallo standard.
Vedi questa risposta precedente sul comportamento di operator new
per dettagli sul diverso comportamento di questo tipo di inizializzazione e quando iniziano (e quando differiscono da c ++ 98 a C ++ 03):
Il punto principale della risposta è:
A volte la memoria restituita dal nuovo operatore viene inizializzata, a volte non dipende dal tipo di POD che stai rinnovando o se è una classe che contiene membri POD e utilizza un costruttore predefinito generato dal compilatore .
- In C ++ 1998 ci sono 2 tipi di inizializzazione: zero e default
- In C ++ 2003 è stato aggiunto un terzo tipo di inizializzazione, inizializzazione del valore.
Per non dire altro, è piuttosto complesso e quando i diversi metodi entrano in gioco sono sottili.
Una cosa di cui bisogna essere consapevoli è che MSVC segue le regole C ++ 98, anche in VS 2008 (VC 9 o cl.exe versione 15.x).
Il frammento seguente mostra che MSVC e Digital Mars seguono le regole C ++ 98, mentre GCC 3.4.5 e Comeau seguono le regole C ++ 03:
#include <cstdio>
#include <cstring>
#include <new>
struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m
int main()
{
char buf[sizeof(B)];
std::memset( buf, 0x5a, sizeof( buf));
// use placement new on the memset'ed buffer to make sure
// if we see a zero result it's due to an explicit
// value initialization
B* pB = new(buf) B(); //C++98 rules - pB->m is uninitialized
//C++03 rules - pB->m is set to 0
std::printf( "m is %d\n", pB->m);
return 0;
}
int
, ma m()
sulla terza riga il valore inizializza m. Importante se si int m;
passa a B m;
. :)
A
e C
non sono usati in questo esempio (sono riportati dall'altra risposta collegata). Anche se C ++ 98 e C ++ 03 usano una terminologia diversa quando descrivono come A
e C
sono costruiti, il risultato è lo stesso in entrambi gli standard. Si struct B
traduce solo in un comportamento diverso.
struct C { C() : m() {}; ~C(); B m; };
, allora avrai m.m
0. Se l'inizializzazione di default è m
come dici C ++ 03, allora m.m
non verrà inizializzata come in C ++ 98.
C ++ 03 Standard 8.5 / 5:
A zero inizializzare un oggetto di mezzi tipo T:
- se T è un tipo scalare (3.9), l'oggetto viene impostato al valore 0 (zero) convertito a T;
- se T è un tipo di classe non sindacale, ciascun membro di dati non statico e ciascun oggetto secondario di classe base è inizializzato a zero;
- 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 a zero;
- se T è un tipo di riferimento, non viene eseguita l'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 per impostazione predefinita;
- in caso contrario, l'oggetto viene inizializzato con zero.Per valore-inizializzare un oggetto di mezzi tipo T:
- se T è un tipo di classe (clausola 9) con un costruttore dall'utente dichiarato (12.1), quindi il costruttore predefinito per T è chiamato (e l'inizializzazione è mal formata 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;
- in caso contrario, l'oggetto viene inizializzato con zeroUn programma che richiede l'inizializzazione di default o l'inizializzazione di valore di un'entità di tipo di riferimento è mal formato. Se T è un tipo con certificazione cv, la versione cv non qualificata di T viene utilizzata per queste definizioni di inizializzazione zero, inizializzazione predefinita e inizializzazione del valore.