Wenn "Test" eine gewöhnliche Klasse ist, gibt es einen Unterschied zwischen:
Test* test = new Test;
et
Test* test = new Test();
Wenn "Test" eine gewöhnliche Klasse ist, gibt es einen Unterschied zwischen:
Test* test = new Test;
et
Test* test = new Test();
Lassen Sie uns pedantisch werden, denn es gibt Unterschiede, die das Verhalten Ihres Codes tatsächlich beeinflussen können. Ein Großteil der folgenden Ausführungen stammt aus Kommentaren zu einer Artikel "Alte neue Sache" .
Manchmal wird der vom new-Operator zurückgegebene Speicher initialisiert, und manchmal nicht, je nachdem, ob der Typ, den Sie neu anlegen, ein POD (einfache alte Daten) oder wenn es sich um eine Klasse handelt, die POD-Mitglieder enthält und einen vom Compiler erzeugten Standardkonstruktor verwendet.
Angenommen:
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
In einem C++98-Compiler sollte folgendes passieren:
new A
- unbestimmter Wert
new A()
- Null-Initialisierung
new B
- Standard-Konstrukt (B::m ist nicht initialisiert)
new B()
- Standard-Konstrukt (B::m ist nicht initialisiert)
new C
- Standard-Konstrukt (C::m ist null-initialisiert)
new C()
- Standard-Konstrukt (C::m ist null-initialisiert)
In einem C++03-konformen Compiler sollten die Dinge folgendermaßen funktionieren:
new A
- unbestimmter Wert
new A()
- value-initialize A, was eine Null-Initialisierung ist, da es sich um ein POD handelt.
new B
- standard-initialisiert (lässt B::m uninitialisiert)
new B()
- Wert-initialisiert B, das alle Felder null-initialisiert, da sein Standard-Ctor vom Compiler generiert und nicht vom Benutzer definiert wird.
new C
- standard-initialisiert C, das den Standard-Ctor aufruft.
new C()
- value-initialisiert C, das den Standard-Ctor aufruft.
In allen Versionen von C++ gibt es also einen Unterschied zwischen new A
et new A()
weil A ein POD ist.
Und es gibt einen Unterschied im Verhalten zwischen C++98 und C++03 für den Fall new B()
.
Dies ist eine der staubigen Ecken von C++, die einen verrückt machen können. Wenn man ein Objekt konstruiert, will/braucht man manchmal die Parens, manchmal kann man sie absolut nicht gebrauchen, und manchmal spielt es keine Rolle.
new Thing();
ist explizit, dass Sie einen Konstruktor aufrufen wollen, während new Thing;
wird so verstanden, dass es Ihnen nichts ausmacht, wenn der Konstruktor nicht aufgerufen wird.
Bei einer Struktur/Klasse mit einem benutzerdefinierten Konstruktor gibt es keinen Unterschied. Bei einem Aufruf für eine triviale Struktur/Klasse (z. B. struct Thing { int i; };
) dann new Thing;
ist wie malloc(sizeof(Thing));
während new Thing();
ist wie calloc(sizeof(Thing));
- wird er mit Null initialisiert.
Der Haken an der Sache liegt dazwischen:
struct Thingy {
~Thingy(); // No-longer a trivial class
virtual WaxOn();
int i;
};
Das Verhalten von new Thingy;
gegen new Thingy();
in diesem Fall zwischen C++98 und C++2003 geändert. Siehe Michael Burrs Erklärung für das Wie und Warum.
Im Allgemeinen haben wir im ersten Fall eine Standardinitialisierung und im zweiten Fall eine Wertinitialisierung.
Zum Beispiel: im Fall von int (POD-Typ):
int* test = new int
- wir haben eine beliebige Initialisierung und der Wert von *test kann beliebig sein.
int* test = new int()
- *Test wird den Wert 0 haben.
Das weitere Verhalten hängt von Ihrem Typ Test ab. Wir haben verschiedene Fälle: Test hat einen Standard-Konstruktor, Test hat einen generierten Standard-Konstruktor, Test enthält ein POD-Mitglied, ein Nicht-POD-Mitglied...
Nein, sie sind identisch. Aber es gibt einen Unterschied zwischen:
Test t; // create a Test called t
et
Test t(); // declare a function called t which returns a Test
Das liegt an der Grundregel von C++ (und C): Wenn etwas eine Deklaration sein kann, dann ist es eine Deklaration.
Editar: Zu den Initialisierungsproblemen in Bezug auf POD- und Nicht-POD-Daten stimme ich zwar mit allem, was gesagt wurde, überein, möchte aber darauf hinweisen, dass diese Probleme nur dann auftreten, wenn das Ding, das neu erstellt oder anderweitig konstruiert wird, keinen benutzerdefinierten Konstruktor hat. Wenn es einen solchen Konstruktor gibt, wird er verwendet. Für 99,99% der vernünftig entworfenen Klassen wird es einen solchen Konstruktor geben, und daher können die Probleme ignoriert werden.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.