1114 Stimmen

Machen die Klammern nach dem Typnamen bei new einen Unterschied?

Wenn "Test" eine gewöhnliche Klasse ist, gibt es einen Unterschied zwischen:

Test* test = new Test;

et

Test* test = new Test();

1034voto

Michael Burr Punkte 320591

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.

  • In C++1998 gibt es 2 Arten der Initialisierung: Null und Standard
  • In C++2003 wurde eine dritte Art der Initialisierung, die Wertinitialisierung, hinzugefügt.

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.

92voto

kfsone Punkte 951

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.

22voto

bayda Punkte 12869

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...

18voto

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.

11voto

Evan Shaw Punkte 22186

Wenn man davon ausgeht, dass Test eine Klasse mit einem definierten Konstruktor ist, gibt es keinen Unterschied. Die letztere Form macht ein wenig deutlicher, dass der Konstruktor von Test ausgeführt wird, aber das war's auch schon.

CodeJaeger.com

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.

Powered by:

X