wake-up-neo.net

Machen die Klammern nach dem Typnamen einen Unterschied zu new?

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

Test* test = new Test;

und

Test* test = new Test();
956
David Read

Lassen Sie uns pedantisch werden, denn es gibt Unterschiede, die sich tatsächlich auf das Verhalten Ihres Codes auswirken können. Ein Großteil des Folgenden stammt aus Kommentaren zu einem "Old New Thing" -Artikel .

Manchmal wird der vom Operator new zurückgegebene Speicher initialisiert, und manchmal hängt er nicht davon ab, ob der Typ, den Sie neu erstellen, ein POD (plain old data) ist, oder ob es sich um eine Klasse handelt, die enthält POD-Mitglieder und verwendet einen vom Compiler generierten Standardkonstruktor.

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

Annehmen:

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 auftreten:

  • new A - unbestimmter Wert
  • new A() - Null-Initialisierung

  • new B - Standardkonstrukt (B :: m ist nicht initialisiert)

  • new B() - Standardkonstrukt (B :: m ist nicht initialisiert)

  • new C - Standardkonstrukt (C :: m ist null-initialisiert)

  • new C() - Standardkonstrukt (C :: m ist null-initialisiert)

In einem C++ 03-konformen Compiler sollten die Dinge so funktionieren:

  • new A - unbestimmter Wert
  • new A() - value-initialize A ist eine Nullinitialisierung, da es sich um einen POD handelt.

  • new B - Standardinitialisierung (lässt B :: m uninitialisiert)

  • new B() - value-initializes B, das alle Felder mit Null initialisiert, da sein Standard-Ctor nicht benutzerdefiniert, sondern vom Compiler generiert wird.

  • new C - initialisiert standardmäßig C, das den Standard-ctor aufruft.

  • new C() - value-initialisiert C, das den Standard-ctor aufruft.

Daher gibt es in allen Versionen von C++ einen Unterschied zwischen new A Und new A(), da 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 Sie verrückt machen können. Wenn Sie ein Objekt konstruieren, möchten/benötigen Sie manchmal die Parens, manchmal können Sie sie überhaupt nicht haben, und manchmal spielt es keine Rolle.

916
Michael Burr

new Thing(); gibt an, dass Sie einen Konstruktor aufrufen möchten, während new Thing; bedeutet, dass Sie nichts dagegen haben, wenn der Konstruktor nicht aufgerufen wird.

Bei Verwendung in einer Struktur/Klasse mit einem benutzerdefinierten Konstruktor besteht kein Unterschied. Wenn auf eine triviale Struktur/Klasse (zB struct Thing { int i; };) Zugegriffen wird, dann ist new Thing; Wie malloc(sizeof(Thing));, wohingegen new Thing(); wie calloc(sizeof(Thing)); ist. - Es wird null initialisiert.

Das gotcha liegt dazwischen:

struct Thingy {
  ~Thingy(); // No-longer a trivial class
  virtual WaxOn();
  int i;
};

Das Verhalten von new Thingy; Vs new Thingy(); hat sich in diesem Fall zwischen C++ 98 und C++ 2003 geändert. Siehe Michael Burrs Erklärung für wie und warum.

58
kfsone

Im Allgemeinen haben wir eine Standardinitialisierung im ersten Fall und eine Wertinitialisierung im zweiten Fall.

Zum Beispiel: bei int (POD-Typ):

  • int* test = new int - wir haben jede Initialisierung und der Wert von * test kann jeder sein.

  • int* test = new int() - * test hat den Wert 0.

das nächste Verhalten hing von Ihrem Typ Test ab. Wir haben unterschiedliche Fälle: Test hat einen fehlerhaften Konstruktor, Test hat einen Standardkonstruktor generiert, Test enthält POD-Mitglied, Nicht-POD-Mitglied ...

17
bayda

Nein, sie sind gleich. Es gibt jedoch einen Unterschied zwischen:

Test t;      // create a Test called t

und

Test t();   // declare a function called t which returns a Test

Dies liegt an der grundlegenden C++ nd C-) Regel: Wenn etwas möglicherweise eine Deklaration sein kann, dann ist es eine Deklaration.

--- (Edit: Bezüglich der Initialisierungsprobleme in Bezug auf POD- und Nicht-POD-Daten, obwohl ich mit allem, was gesagt wurde, einverstanden bin, möchte ich nur darauf hinweisen, dass diese Probleme nur zutreffen, wenn das Ding neu ist oder anders konstruiert hat keinen benutzerdefinierten Konstruktor. Wenn es einen solchen Konstruktor gibt, wird er verwendet. Für 99,99% der sinnvoll gestalteten Klassen wird es einen solchen Konstruktor geben, sodass die Probleme ignoriert werden können.

16
anon

Angenommen, Test ist eine Klasse mit einem definierten Konstruktor, gibt es keinen Unterschied. Die letztere Form macht es ein wenig klarer, dass der Konstruktor von Test ausgeführt wird, aber das war es auch schon.

10
Evan Shaw