`Base * b = новая база;` vs `Base * b = новая база ();` без определения собственного конструктора - PullRequest
10 голосов
/ 13 сентября 2010

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

Ответы [ 3 ]

8 голосов
/ 13 сентября 2010

Инициализация - это своего рода PITA, которой нужно следовать в стандарте ... Тем не менее, два уже существующих ответа неверны в том, что они пропускают, и это заставляет их утверждать, что нет никакой разницы.

Существуетогромная разница между вызовами new T и new T() в классах, где нет определенного пользователем конструктора.В первом случае объект будет default-initialized , тогда как во втором случае он будет `value-initialized *.Если объект содержит какой-либо подобъект 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 имеет user (по определению пользователя, который включает в себя стандартного средства записи библиотеки), он будет вызывать такой конструктор, но он не будет выполнять никакой реальной инициализации члена x.

То есть для класса с конструктором по умолчанию, предоставленным пользователем, new T и new T() одинаковы.Для класса без такого конструктора это зависит от содержимого класса.

3 голосов
/ 13 сентября 2010

РЕДАКТИРОВАТЬ: СМОТРИТЕ ОТВЕТ @David - ЭТО НЕПРАВИЛЬНО, НО НЕ МОЖЕТ УДАЛИТЬ, ПОТОМУ ЧТО ЭТО ПРИНЯТО

Нет разницы в обоих случаях - не имеет значения, определяете ли вы свой конструктор или нет.

Единственное отличие состоит в том, что для примитивных типов (т. Е. int или float) добавление () инициализирует значение до нуля. ( Демонстрация на кодовой панели )

См. Этот пример (вывод на кодовая панель )

#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;
}
0 голосов
/ 13 сентября 2010

Как упоминал Билли, оба они одно и то же.

Это называется «синтаксис инициализации значения» ($ 8,5 / 7).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...