Was bedeuten die folgenden Sätze in C ++:
Nullinitialisierung,
Standardinitialisierung und
Wertinitialisierung
Was sollte ein C ++ - Entwickler über sie wissen?
Was bedeuten die folgenden Sätze in C ++:
Nullinitialisierung,
Standardinitialisierung und
Wertinitialisierung
Was sollte ein C ++ - Entwickler über sie wissen?
Antworten:
Zu erkennen ist, dass die 'Wertinitialisierung' mit dem C ++ 2003-Standard neu ist - sie existiert nicht im ursprünglichen Standard von 1998 (ich denke, dies ist möglicherweise der einzige Unterschied, der mehr als eine Klarstellung ist). Siehe die Antwort von Kirill V. Lyadvinsky für die Definitionen direkt aus dem Standard.
In dieser vorherigen Antwort zum Verhalten von finden Sie operator new
Details zum unterschiedlichen Verhalten dieser Art der Initialisierung und wann sie aktiviert werden (und wann sie sich von c ++ 98 bis C ++ 03 unterscheiden):
Der Hauptpunkt der Antwort ist:
Manchmal wird der vom neuen Operator zurückgegebene Speicher initialisiert, und manchmal hängt es nicht davon ab, ob der Typ, den Sie neu erstellen, ein POD ist oder ob es sich um eine Klasse handelt, die POD-Mitglieder enthält und einen vom Compiler generierten Standardkonstruktor verwendet .
- In C ++ 1998 gibt es zwei Arten der Initialisierung: Null und Standard
- In C ++ 2003, einem dritten Initialisierungstyp, wurde die Wertinitialisierung hinzugefügt.
Um es gelinde auszudrücken, es ist ziemlich komplex und wenn die verschiedenen Methoden zum Einsatz kommen, sind sie subtil.
Zu beachten ist, dass MSVC auch in VS 2008 (VC 9 oder cl.exe Version 15.x) den C ++ 98-Regeln folgt.
Das folgende Snippet zeigt, dass MSVC und Digital Mars den C ++ 98-Regeln folgen, während GCC 3.4.5 und Comeau den C ++ 03-Regeln folgen:
#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
, aber m()
in der dritten Zeile initialisiert der Wert m. Wichtig , wenn Sie ändern int m;
zu B m;
. :)
A
und C
werden in diesem Beispiel nicht verwendet (sie werden von der anderen verknüpften Antwort übernommen). Obwohl C ++ 98 und C ++ 03 unterschiedliche Begriffe verwenden, um zu beschreiben, wie A
und wie sie aufgebaut C
sind, ist das Ergebnis in beiden Standards das gleiche. Führt nur struct B
zu unterschiedlichem Verhalten.
struct C { C() : m() {}; ~C(); B m; };
, dann haben Sie m.m
0. Aber wenn es standardmäßig initialisiert würde, m
wie Sie sagen, dass C ++ 03 es tut, dann m.m
würde es nicht wie in C ++ 98 initialisiert werden.
C ++ 03 Standard 8.5 / 5:
Ein Objekt vom Typ T auf Null zu initialisieren bedeutet:
- Wenn T ein Skalartyp (3.9) ist, wird das Objekt auf den Wert 0 (Null) gesetzt, der in T umgewandelt wird;
- Wenn T ein Nicht-Vereinigungsklassentyp ist, wird jedes nicht statische Datenelement und jedes Basisklassen-Unterobjekt mit Null initialisiert.
- Wenn T ein Vereinigungstyp ist, wird das zuerst benannte Datenelement des Objekts mit Null initialisiert.
- Wenn T ein Array-Typ ist, wird jedes Element mit Null initialisiert.
- Wenn T ein Referenztyp ist, wird keine Initialisierung durchgeführt.Die Standardinitialisierung eines Objekts vom Typ T bedeutet:
- Wenn T ein Nicht-POD-Klassentyp ist (Abschnitt 9), wird der Standardkonstruktor für T aufgerufen (und die Initialisierung ist fehlerhaft, wenn T keinen zugänglichen Standardkonstruktor hat);
- Wenn T ein Array-Typ ist, wird jedes Element standardmäßig initialisiert.
- Andernfalls wird das Objekt mit Null initialisiert.Die Wertinitialisierung eines Objekts vom Typ T bedeutet:
- Wenn T ein Klassentyp (Klausel 9) mit einem vom Benutzer deklarierten Konstruktor (12.1) ist, wird der Standardkonstruktor für T aufgerufen (und die Initialisierung ist falsch, wenn T. hat keinen zugänglichen Standardkonstruktor);
- Wenn T ein nicht vereinigter Klassentyp ohne einen vom Benutzer deklarierten Konstruktor ist, wird jedes nicht statische Datenelement und jede Basisklassenkomponente von T wertinitialisiert.
- Wenn T ein Array-Typ ist, wird jedes Element mit einem Wert initialisiert.
- Andernfalls wird das Objekt mit Null initialisiertEin Programm, das die Standardinitialisierung oder Wertinitialisierung einer Entität des Referenztyps fordert, ist fehlerhaft. Wenn T ein cv-qualifizierter Typ ist, wird die cv-nicht qualifizierte Version von T für diese Definitionen von Nullinitialisierung, Standardinitialisierung und Wertinitialisierung verwendet.