Ответ
malloc() и new — операторы выделения памяти, фундаментально различающиеся по своей семантике в C++.
malloc() (из C) — функция, выделяющая блок неинициализированной памяти заданного размера в байтах. Возвращает void*, который требует явного приведения типа. Она не вызывает конструкторы объектов C++.
new (оператор C++) — выполняет две операции:
- Выделяет достаточную память для объекта (или массива объектов).
- Вызывает конструктор для инициализации объекта в этой памяти.
| Сравнительная таблица: | Критерий | malloc() / free() |
new / delete |
|---|---|---|---|
| Язык | C / C++ (как legacy) | C++ | |
| Возвращаемый тип | void* (требует приведения) |
Типизированный указатель (например, MyClass*) |
|
| Инициализация | Нет (память содержит «мусор») | Да (вызывается конструктор) | |
| Размер | Задается в байтах (sizeof) |
Вычисляется компилятором автоматически | |
| Обработка ошибок | Возвращает nullptr |
Генерирует исключение std::bad_alloc |
|
| Перегрузка | Нет | Да, можно перегружать для классов | |
| Совместимость | Работает с типами C (POD) | Работает с любыми типами C++ |
Примеры:
// 1. Выделение памяти для примитивного типа
int* p1 = (int*)malloc(sizeof(int)); // Память не инициализирована
*p1 = 10; // Необходима ручная инициализация
free(p1);
int* p2 = new int(10); // Память выделена И инициализирована значением 10
delete p2;
// 2. Выделение памяти для объекта класса
class Widget {
std::string name;
public:
Widget(const std::string& n) : name(n) {}
};
// malloc: ТОЛЬКО память. Конструктор не вызван. ОПАСНО!
Widget* w1 = (Widget*)malloc(sizeof(Widget));
// w1->name находится в неопределенном состоянии. Использование -> UB.
free(w1); // Деструктор не вызван.
// new: Память + инициализация.
Widget* w2 = new Widget("test"); // Вызывается конструктор Widget(...)
delete w2; // Вызывается деструктор ~Widget()
Вывод: В C++ для объектов с нетривиальной логикой всегда используйте new/delete или, что лучше, умные указатели. malloc()/free() уместны только для низкоуровневого управления сырой памятью или при взаимодействии с C-библиотеками.
Ответ 18+ 🔞
А, ну вот, опять про эту парочку — malloc и new. Сидят как два кота на заборе, вроде оба память выделяют, а на деле разница — хуй с горы и манда с ушами. Слушай сюда, разжую.
malloc() — это старый дед из Си. Приходит, находит кусок памяти нужного размера в байтах, тыкает в него пальцем — вот, бери. А что в этом куске лежало до этого — ему похуй. Мусор, пыль, старые биты от вчерашней сессии. Возвращает он тебе void*, то есть указатель в никуда. И ты ещё должен сам, как полупидор, вручную привести его к нужному типу. И главное — конструкторы он не вызывает. Вообще. Ноль. Просто сырая, нестираная память.
new — это уже наш, цивилизованный C++шный оператор. Он делает сразу две вещи: сначала находит память, а потом — внимание — вызывает конструктор и аккуратно размещает там твой объект. Всё чисто, прибрано, работает. Возвращает сразу правильный, типизированный указатель.
Вот тебе табличка, чтобы совсем охуеть от контраста:
| Критерий | malloc() / free() |
new / delete |
|---|---|---|
| Откуда ноги растут | C, старьё | C++, нормально |
| Что возвращает | void* (хуй пойми что, надо кастовать) |
Чёткий указатель (например, MyClass*) |
| Инициализация | Нет, там овердохуища мусора | Да, конструктор дергается автоматом |
| Размер | Сам считай в байтах, sizeof мучай |
Компилятор сам всё посчитает |
| Если не повезло | Молча вернёт nullptr, ищи сам, где сломалось |
Бросит исключение std::bad_alloc — лови, если не трус |
| Перегрузка | Никакой, функция и всё | Да, можно для своих классов переопределить |
| С кем дружит | С голыми структурами из Си (POD) | С любыми сложными типами C++ |
А теперь смотри, как это на практике выглядит, чтобы волнение ебать от понимания:
// 1. Примитивный тип, типа int
int* p1 = (int*)malloc(sizeof(int)); // Выделили память. А ЧТО ТАМ? Хуй знает. Мусор.
*p1 = 10; // Теперь сам, вручную, присвоил значение. Напрягся.
free(p1); // Освободил.
int* p2 = new int(10); // Всё в одной строке: и память выделил, И число 10 туда запихал.
delete p2; // Красота.
// 2. А теперь класс, чтобы совсем пиздец
class Widget {
std::string name;
public:
Widget(const std::string& n) : name(n) {} // Конструктор, который имя сохраняет
};
// malloc: ЁПТА, ЧТО ТЫ ТВОРИШЬ?!
Widget* w1 = (Widget*)malloc(sizeof(Widget)); // Память выделил. А объект-то НЕ СОЗДАЛ.
// Конструктор не вызвался. Поле `name` — неинициализированная строка. Пиздец полный.
// w1->name.обращаться_сюда() — это билет в ад, неопределённое поведение, UB.
free(w1); // Просто память освободил. Деструктор не дернулся. Утечки? Возможно.
// new: Вот так надо, чувак.
Widget* w2 = new Widget("test"); // 1. Память. 2. Конструктор Widget("test") вызвался. Всё работает.
delete w2; // 1. Деструктор ~Widget() вызвался. 2. Память освободилась. Идеально.
Итог, блядь, простой: если ты пишешь на чистом C++ и работаешь с объектами (а тем более с классами, где есть конструкторы, деструкторы, наследование — вся эта ёперная балетная труппа), то используй new/delete. А лучше — умные указатели (unique_ptr, shared_ptr), чтобы вообще об этом не думать.
malloc()/free() оставь для каких-то совсем низкоуровневых поделок, работы с сишными библиотеками или когда тебе реально нужен кусок сырой, неинициализированной памяти. Во всех остальных случаях — это путь в никуда, доверия ебать ноль.