Если 'Test' представляет собой обычный класс, есть ли разница между:Составляются ли скобки после названия типа с новым?
Test* test = new Test;
и
Test* test = new Test();
Если 'Test' представляет собой обычный класс, есть ли разница между:Составляются ли скобки после названия типа с новым?
Test* test = new Test;
и
Test* test = new Test();
Давайте сделаем педантичным, потому что есть различия, которые могут действительно повлиять на поведение вашего кода. Из комментариев, сделанных к "Old New Thing" article, взята значительная часть.
Иногда память, возвращаемая новым оператором, будет инициализирована, и иногда она не зависит от того, является ли тип, который вы новичок, POD (plain old data), или если это класс, который содержит элементы POD и использует компилятор -генерированный конструктор по умолчанию.
Предположим:
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()
- нуль-инициализации
new B
- конструкция по умолчанию (Б :: м не инициализирован)
new B()
- по умолчанию конструкция (Б :: м не инициализирован)
new C
- конструкция по умолчанию (C :: м равна нулю инициализирован)
new C()
- конструкт по умолчанию (C :: м равен нулю инициализирован)В C++ 03 компилятор с совместимой, все должно работать так:
new A
- неопределенное значениеnew A()
- значение инициализации A, которая является нулевой инициализации, так как это стручка.
new B
- по умолчанию инициализирует (уходит B :: м) неинициализированного
new B()
- значение инициализирует В, который нулевой инициализирует все поля, так как его по умолчанию является т е р компилятора, в отличие от определяемого пользователя.
new C
- по умолчанию инициализирует C, который вызывает значение по умолчанию ctor.
new C()
- значение инициализирует C, который вызывает значение по умолчанию ctor.Так во всех версиях C++ есть разница между new A
и new A()
, потому что А является POD.
И есть разница в поведении между C++ 98 и C++ 03 для случая new B()
.
Это один из пыльных уголков C++, который может свести вас с ума. Когда вы строите объект, иногда вам нужны/нужны парнеры, иногда вы их абсолютно не можете, и иногда это не имеет значения.
Для 'new C' и' new C() 'под C++ 03,' m' осталось неинициализированным? Как насчет 'struct D {D(): {} int m; } '(т. е. не-POD из-за пользовательского ctor, но m не упоминается)? –
Кажется, что моя 'struct D' была упомянута позже в этой ветке« New New Thing »! Для «новых D» и «новых D()', 'm' не инициализируется. –
@j_random_hacker, 'new A()' будет по умолчанию инициализировать объект в C++ 98, как это происходит с помощью 'new B()', 'new B',' new C() 'и' new C', но * не * с 'новым A'. То есть инициализация по умолчанию всегда выполняется в C++ 98, если: 1) класс является не-POD, а инициализатор отсутствует, или 2) инициализатором является '()'. default-initialization zero - инициализирует объект, если это POD, но вызывает конструктор по умолчанию для не-POD. –
Нет, они одинаковы. Но есть разница между:
Test t; // create a Test called t
и
Test t(); // declare a function called t which returns a Test
Это происходит потому, что основной C++ (и C) правила: Если что-то может быть возможно заявление, то это заявление.
Edit: Re вопросов, касающихся инициализации POD и не-POD данных, в то время как я согласен со всем, что было сказано, я просто хотел бы отметить, что эти вопросы относятся только если вещь быть new'd или иначе построенный не имеет определяемого пользователем конструктора. Если есть такой конструктор, он будет использоваться. Для 99,99% разумно спроектированных классов будет такой конструктор, и поэтому проблемы могут быть проигнорированы.
Обратите внимание, что это особенно важный момент, потому что строка «Test t (5)»; эквивалентно «Test t = Test (5)»; - но «Test t()»; очень отличается от «Test t = Test();». +1 – ojrac
-1, я не согласен с вашим утверждением, что проблемы можно игнорировать. Вам не обязательно знать правила точно, но вы должны знать о них, если вам нужно создать новый класс без пользовательского конструктора по умолчанию (вы должны либо написать конструктор, либо найти правила). – avakar
-1 для известного неверного ответа. Ваш Редактор игнорирует наличие кода, написанного бывшими программистами C, которые не понимали/не использовали конструкторы. – Tom
Предполагая, что Test является классом с определенным конструктором, нет никакой разницы. Последняя форма немного упрощает конструктор Test, но это все.
В общем случае мы инициализируем по умолчанию в первом случае и инициализацию значения во втором случае.
Например: в случае с INT (типа POD):
int* test = new int
- мы инициализацию и значение * теста может быть любым.
int* test = new int()
- * тест будет иметь значение 0.
следующее поведение зависит от типа теста. У нас есть дефференциальные случаи: Test имеет конструктор defult, Test создал конструктор по умолчанию, Test содержит член POD, член не POD ...
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. См. Объяснение Майкла Барра о том, как и почему.
Это связано с (но не идентичным) http://stackoverflow.com/questions/1613341/what-do-the-following-phrases-mean-in-c-zero-default-and-value-initializati –
Просто используйте новый тест(), чтобы убедиться, что он инициализирован нулем. – Sung