Подтвердить что ты не робот

`Base * b = new Base;` vs `Base * b = new Base();` без определения моего собственного конструктора

Если я не определяю свой собственный конструктор, есть ли разница между Base *b = new Base; vs Base *b = new Base();?

4b9b3361

Ответ 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).

Объект, инициализатор которого является пустой набор скобок, т.е.(), должен инициализироваться значением.