Есть ли в скобках после имени типа разница с новым? - PullRequest
946 голосов
/ 06 марта 2009

Если 'Test' - обычный класс, есть ли разница между:

Test* test = new Test;

и

Test* test = new Test();

Ответы [ 5 ]

908 голосов
/ 07 марта 2009

Давайте станем педантичными, потому что есть различия, которые могут реально повлиять на поведение вашего кода. Многое из следующего взято из комментариев, сделанных к статье "Старое новое" .

Иногда память, возвращаемая новым оператором, будет инициализирована, и иногда это не будет зависеть от того, является ли тип, который вы обновляете, POD (обычные старые данные) или если класс, который содержит члены POD и использует сгенерированный компилятором конструктор по умолчанию.

  • В C ++ 1998 есть 2 типа инициализации: ноль и по умолчанию
  • В C ++ 2003 был добавлен третий тип инициализации, инициализация значения.

Предположим:

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

В компиляторе C ++ 98 должно происходить следующее:

  • new A - неопределенное значение
  • new A() - инициализация нуля

  • new B - конструкция по умолчанию (B :: m неинициализирована)

  • new B() - конструкция по умолчанию (B :: m неинициализирована)

  • new C - конструкция по умолчанию (C :: m инициализируется нулями)

  • new C() - конструкция по умолчанию (C :: m инициализируется нулями)

В компиляторе, совместимом с C ++ 03, все должно работать так:

  • new A - неопределенное значение
  • new A() - инициализация значения A, то есть инициализация с нуля, поскольку это POD.

  • new B - инициализируется по умолчанию (оставляет B :: m неинициализированным)

  • new B() - инициализирует значение B, которое инициализирует нулями все поля, поскольку его ctor по умолчанию генерируется компилятором, а не определяется пользователем.

  • new C - инициализирует по умолчанию C, который вызывает ctor по умолчанию.

  • new C() - инициализирует значение C, которое вызывает ctor по умолчанию.

Так что во всех версиях C ++ есть разница между new A и new A(), потому что A - это POD.

И есть разница в поведении между C ++ 98 и C ++ 03 для случая new B().

Это один из пыльных уголков C ++, который может свести вас с ума. При создании объекта иногда вам нужны / нужны парены, иногда вы совершенно не можете их получить, а иногда это не имеет значения.

56 голосов
/ 15 февраля 2013

new Thing(); явно означает, что вы хотите, чтобы конструктор вызывался, тогда как new Thing; означает, что вы не против, если конструктор не вызывается.

Если используется в структуре / классе с определяемым пользователем конструктором, разницы нет. Если вызывается для тривиальной структуры / класса (например, struct Thing { int i; };), то new Thing; похоже на malloc(sizeof(Thing));, тогда как new Thing(); похоже на calloc(sizeof(Thing)); - оно инициализируется нулем.

Гоча лежит между:

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

Поведение new Thingy; против new Thingy(); в этом случае изменилось между C ++ 98 и C ++ 2003. См. Объяснение Майкла Берра о том, как и почему.

18 голосов
/ 06 марта 2009

Нет, они одинаковые. Но есть разница между:

Test t;      // create a Test called t

и

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

Это из-за основного правила C ++ (и C): если что-то может быть объявлением, то это объявление.

Редактировать: Относительно проблем инициализации, связанных с данными POD и не POD, хотя я согласен со всем, что было сказано, я просто хотел бы отметить, что эти проблемы применимы, только если что-то новое 'd или иным образом построенный не имеет пользовательского конструктора. Если есть такой конструктор, он будет использован. Для 99,99% разумно разработанных классов будет такой конструктор, и поэтому проблемы можно игнорировать.

16 голосов
/ 06 марта 2009

В общем случае мы имеем инициализацию по умолчанию в первом случае и инициализацию значения во втором случае.

Например: в случае с int (тип POD):

  • int* test = new int - у нас есть любая инициализация и значение * test может быть любым.

  • int* test = new int() - * тест будет иметь значение 0.

следующее поведение зависит от вашего типа Test. У нас есть разные случаи: Test имеет конструктор defult, Test сгенерировал конструктор по умолчанию, Test содержит член POD, не член POD ...

10 голосов
/ 06 марта 2009

Предполагая, что Test - это класс с определенным конструктором, нет никакой разницы. Последняя форма немного упрощает работу конструктора Test, но это все.

...