Соответствуют ли скобки после имени типа с новым?
Если "Тест" - обычный класс, есть ли разница между:
Test* test = new Test;
и
Test* test = new Test();
Ответы
Ответ 1
Позвольте получить педантичность, потому что есть различия, которые могут фактически повлиять на поведение вашего кода. Из комментариев, сделанных в статье "Old New Thing" , говорится следующее:
Иногда память, возвращаемая новым оператором, будет инициализирована, и иногда это не зависит от того, является ли тип, который вы новичок, POD (простые старые данные), или если это класс, содержащий элементы POD, и использует созданный компилятором конструктор по умолчанию.
- В С++ 1998 существует 2 типа инициализации: ноль и значение по умолчанию
- В С++ 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
В компиляторе С++ 98 должно произойти следующее:
-
new A
- неопределенное значение
-
new A()
- zero-initialize
-
new B
- конструктор по умолчанию (B:: m не инициализирован)
-
new B()
- конструктор по умолчанию (B:: m не инициализирован)
-
new C
- конструктор по умолчанию (C:: m инициализируется нулем)
-
new C()
- конструктор по умолчанию (C:: m инициализируется нулем)
В компиляторе, совместимом с С++ 03, все должно работать так:
-
new A
- неопределенное значение
-
new A()
- инициализировать значение A, которое является нулевой инициализацией, поскольку это POD.
-
new B
- default инициализирует (оставляет B:: m неинициализированным)
-
new B()
- value-initializes B, который нуль инициализирует все поля, поскольку его по умолчанию ctor является компилятором, генерируемым в отличие от пользовательского.
-
new C
- по умолчанию инициализирует C, который вызывает значение по умолчанию ctor.
-
new C()
- значение инициализирует C, который вызывает значение по умолчанию ctor.
Итак, во всех версиях С++ существует разница между new A
и new A()
, потому что A является POD.
И есть разница в поведении между С++ 98 и С++ 03 для случая new B()
.
Это один из пыльных углов С++, который может свести вас с ума. Когда вы строите объект, иногда вам нужны/нужны парнеры, иногда вы их абсолютно не можете, и иногда это не имеет значения.
Ответ 2
new Thing();
является явным, что вы хотите вызвать конструктор, тогда как new Thing;
берется, чтобы подразумевать, что вы не возражаете, если конструктор не вызван.
Если используется в struct/class с определяемым пользователем конструктором, нет никакой разницы. Если вызывается тривиальная структура/класс (например, 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;
vs new Thingy();
в этом случае изменилось между С++ 98 и С++ 2003. См. Объяснение Майкла Барра о том, как и почему.
Ответ 3
Нет, они одинаковы. Но есть разница между:
Test t; // create a Test called t
и
Test t(); // declare a function called t which returns a Test
Это из-за базового правила С++ (и C): если что-то может быть объявлением, то это объявление.
Изменить: Повторите инициализацию проблем, связанных с данными POD и не-POD, в то время как я согласен со всем, что было сказано, я хотел бы просто отметить, что эти проблемы применимы только в том случае, new'd или иным образом не имеет определяемого пользователем конструктора. Если есть такой конструктор, он будет использоваться. Для 99,99% разумно спроектированных классов будет такой конструктор, и поэтому проблемы могут быть проигнорированы.
Ответ 4
В общем случае мы инициализируем по умолчанию в первом случае и инициализацию значения во втором случае.
Например:
в случае с int (тип POD):
-
int* test = new int
- у нас есть любая инициализация, а значение * test может быть любым.
-
int* test = new int()
- * test будет иметь значение 0.
следующее поведение зависит от вашего типа Test.
У нас есть дефференциальные случаи: Test имеет конструктор defult, Test создал конструктор по умолчанию, Test содержит член POD, член не POD...
Ответ 5
Предполагая, что Test является классом с определенным конструктором, нет никакой разницы. Последняя форма немного облегчает работу конструктора Test, но об этом.