Существует одна большая разница между malloc
и new
. malloc
выделяет память. Это хорошо для C, потому что в C кусок памяти является объектом.
В C ++, если вы не имеете дело с типами POD (которые похожи на типы C), вы должны вызвать конструктор в ячейке памяти, чтобы фактически иметь там объект. Типы без POD очень распространены в C ++, так как многие функции C ++ делают объект автоматически не POD.
new
выделяет память , а создает объект в этой ячейке памяти. Для не POD-типов это означает вызов конструктора.
Если вы делаете что-то вроде этого:
non_pod_type* p = (non_pod_type*) malloc(sizeof *p);
Указатель, который вы получаете, не может быть разыменован, поскольку он не указывает на объект. Вам нужно вызвать конструктор, прежде чем вы сможете его использовать (и это делается с помощью размещения new
).
Если, с другой стороны, вы делаете:
non_pod_type* p = new non_pod_type();
Вы получаете указатель, который всегда действителен, потому что new
создал объект.
Даже для типов POD между ними есть существенная разница:
pod_type* p = (pod_type*) malloc(sizeof *p);
std::cout << p->foo;
Этот фрагмент кода выведет неопределенное значение, поскольку объекты POD, созданные с помощью malloc
, не инициализируются.
С помощью new
вы можете указать конструктор для вызова и, таким образом, получить четко определенное значение.
pod_type* p = new pod_type();
std::cout << p->foo; // prints 0
Если вы действительно этого хотите, вы можете использовать new
для получения неинициализированных объектов POD. См. этот другой ответ для получения дополнительной информации об этом.
Другое различие заключается в поведении при неудаче. Если не удается выделить память, malloc
возвращает нулевой указатель, а new
выдает исключение.
Первый требует, чтобы вы проверяли каждый указатель, возвращенный перед его использованием, тогда как последний всегда будет выдавать действительные указатели.
По этим причинам в коде C ++ вы должны использовать new
, а не malloc
. Но даже в этом случае вам не следует использовать new
«в открытую», потому что он получает ресурсы, которые вам нужно будет выпустить позже. Когда вы используете new
, вы должны немедленно передать его результат в класс управления ресурсами:
std::unique_ptr<T> p = std::unique_ptr<T>(new T()); // this won't leak