Frage Machen die Klammern hinter dem Typnamen einen Unterschied zu neuen?


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

Test* test = new Test;

und

Test* test = new Test();

891
2018-03-06 19:39


Ursprung


Antworten:


Lassen Sie uns pedantisch werden, denn es gibt Unterschiede, die das Verhalten Ihres Codes beeinflussen können. Viele der folgenden Aussagen stammen aus Kommentaren zu einem "Old New Thing" -Artikel.

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 ist POD (einfache alte Daten)oder wenn es sich um eine Klasse handelt, die POD-Member enthält und einen vom Compiler generierten Standardkonstruktor verwendet.

  • In C ++ 1998 gibt es 2 Arten der Initialisierung: Null und Standard
  • In C ++ 2003 wurde eine 3. Art der Initialisierung, Wert Initialisierung 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 das folgende auftreten:

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

  • 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, das ist Null-Initialisierung, da es ein POD ist.

  • new B    - default-initialisiert (lässt B :: m nicht initialisiert)

  • new B()  - value-initialisiert B, das alle Felder null initialisiert, da sein Standard-ctor vom Compiler generiert und nicht vom Benutzer definiert wurde.

  • new C    - default-initialisiert C, wodurch der Standard-Ctor aufgerufen wird.

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

Also in allen Versionen von C ++ gibt es einen Unterschied zwischen new A und 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 dich verrückt machen kann. Wenn Sie ein Objekt konstruieren, wollen / brauchen Sie manchmal die Parens, manchmal können Sie sie absolut nicht haben, und manchmal ist es egal.


860
2018-03-06 21:01



new Thing(); ist explizit, dass Sie einen Konstruktor namens whith wollen new Thing; Man nimmt an, dass es Ihnen nichts ausmacht, wenn der Konstruktor nicht aufgerufen wird.

Wenn es in einer Struktur / Klasse mit einem benutzerdefinierten Konstruktor verwendet wird, gibt es keinen Unterschied. Wenn eine triviale Struktur / Klasse aufgerufen wird (z. struct Thing { int i; };) dann new Thing; ist wie malloc(sizeof(Thing)); wohingegen new Thing(); ist wie calloc(sizeof(Thing)); - Es wird Null initialisiert.

Die Gotcha liegt dazwischen:

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

Das Verhalten von new Thingy; vs new Thingy(); In diesem Fall wurde zwischen C ++ 98 und C ++ 2003 gewechselt. Siehe Michael Burrs Erklärung für wie und warum.


49
2018-02-15 19:57



Nein, sie sind gleich. Aber es gibt 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 Regel von C ++ (und C): Wenn etwas möglicherweise eine Deklaration sein kann, dann ist es eine Deklaration.

Bearbeiten: Zu den Initialisierungsproblemen bezüglich POD- und Nicht-POD-Daten, während ich mit allem, was gesagt wurde, einverstanden bin, möchte ich nur darauf hinweisen, dass diese Probleme nur dann zutreffen, wenn das Ding, das neu oder anders gebaut wird, keinen Benutzer hat. Definierter Konstruktor. Wenn es einen solchen Konstruktor gibt, wird es verwendet. Für 99,99% der vernünftig entworfenen Klassen wird es einen solchen Konstruktor geben, und so können die Probleme ignoriert werden.


16
2018-03-06 19:42



Im Allgemeinen haben wir Default-Initialisierung im ersten Fall und Wert-Initialisierung im zweiten Fall.

Beispielsweise: im Fall mit int (POD-Typ):

  • int* test = new int - Wir haben irgendeine Initialisierung und der Wert von * test kann beliebig sein.

  • int* test = new int() - * Test wird 0 Wert haben.

Das nächste Verhalten hängt von Ihrem Typ Test ab. Wir haben unterschiedliche Fälle: Test hat default Konstruktor, Test hat Standardkonstruktor generiert, Test enthält POD Mitglied, nicht POD Mitglied ...


16
2018-03-06 20:00



Wenn Test eine Klasse mit einem definierten Konstruktor ist, gibt es keinen Unterschied. Die letztere Form macht es ein wenig klarer, dass Testers Konstruktor läuft, aber das ist schon alles.


10
2018-03-06 19:42