Если я не определяю свой собственный конструктор, есть ли разница между Base *b = new Base;
vs Base *b = new Base();
?
Ответ 1
Инициализация - это своего рода PITA, чтобы следовать в стандарте... Тем не менее, два уже существующих ответа неверны в том, что они пропускают, и это заставляет их утверждать, что нет никакой разницы.
Существует огромная разница между вызовами new T
и new T()
в классах, где нет определяемого пользователем конструктора. В первом случае объект будет инициализирован по умолчанию, а во втором случае он будет "инициализирован значением". Если объект содержит какой-либо подобъект POD, то первый оставит подбот POD неинициализированным, а второй установит каждый подэлемент в 0.
struct test {
int x;
std::string s;
};
int main() {
std::auto_ptr<test> a( new test );
assert( a->s.empty() ); // ok, s is string, has default constructor
// default constructor sets it to empty
// assert( a->x == 0 ); // this cannot be asserted, the value of a->x is
// undefined
std::auto_ptr<test> b( new test() );
assert( b->s.empty() ); // again, the string constructor sets to empty
assert( b->x == 0 ); // this is guaranteed by *value-initialization*
}
Для длинной дороги... default-initialize для определенного пользователем класса означает вызов конструктора по умолчанию. В случае без конструктора по умолчанию, предоставленного пользователем, он будет вызывать неявно определенный конструктор по умолчанию, который эквивалентен конструктору с пустым списком инициализации и пустым телом (test::test() {}
), что, в свою очередь, приведет к инициализации по умолчанию для каждого не-POD подобъектом, и оставить все подобъекты POD неинициализированными. Поскольку std::string
имеет пользователя (по некоторому определению пользователя, который включает в себя стандартную библиотеку), предоставленный конструктор, он вызывается таким конструктором, но он не будет выполнять никакой реальной инициализации в члене x
.
То есть для класса с предоставленным пользователем конструктором по умолчанию new T
и new T()
совпадают. Для класса без такого конструктора это зависит от содержимого класса.
Ответ 2
РЕДАКТИРОВАТЬ: СМОТРИТЕ @ОТВЕТ ОТВЕТ - ЭТО НЕПРАВИЛЬНО, НО Я НЕ МОГУ УДАЛЯТЬ ЭТО ПОТОМУ ЧТО ЭТО ПРИНЯТОЕ
В обоих случаях нет разницы - неважно, определяете ли вы свой собственный конструктор или нет.
Единственное различие заключается в том, что для примитивных типов (т.е. int
или float
) добавление ()
будет инициализировать значение до нуля. (Демонстрация на Codepad)
См. этот пример (вывод находится на codepad)
#include <iostream>
struct ConstructorChecker
{
ConstructorChecker()
{
std::cout << "Hey look! A new constructor checker!" << std::endl;
}
};
struct BasicClass
{
};
int main()
{
//Note constructor called in both cases.
ConstructorChecker *one = new ConstructorChecker;
delete one;
ConstructorChecker *two = new ConstructorChecker();
delete two;
//Same deal -- just because the compiler provides the constructor doesn't mean
//it behaves any differently.
BasicClass *basic = new BasicClass;
delete basic;
BasicClass *basic2 = new BasicClass();
delete basic2;
return 0;
}
Ответ 3
Как отметил Билли, оба они одинаковы.
Это называется синтаксисом инициализации значения ($ 8.5/7).
Объект, инициализатор которого является пустой набор скобок, т.е.(), должен инициализироваться значением.