Ответ
free() и delete — это механизмы освобождения памяти, которые нельзя смешивать.
free() — функция стандартной библиотеки C (<cstdlib>). Она освобождает «сырую» память, выделенную функциями malloc(), calloc() или realloc(). free() не знает о типах C++ и не вызывает деструкторы объектов.
delete — оператор C++. Он выполняет две операции:
- Вызывает деструктор объекта (для освобождения ресурсов: закрытия файлов, освобождения другой памяти и т.д.).
- Освобождает память, выделенную для этого объекта оператором
new.
Пример, демонстрирующий разницу:
#include <cstdlib>
class ResourceHolder {
int* data;
public:
ResourceHolder() { data = new int[100]; std::cout << "Resource allocatedn"; }
~ResourceHolder() { delete[] data; std::cout << "Resource freedn"; }
};
int main() {
// C-стиль: НЕВЕРНО для объектов C++
ResourceHolder* rh1 = (ResourceHolder*)malloc(sizeof(ResourceHolder));
// Конструктор НЕ вызван! data не инициализирован.
free(rh1); // Деструктор НЕ вызван! Утечка памяти для `data`.
// C++-стиль: ПРАВИЛЬНО
ResourceHolder* rh2 = new ResourceHolder(); // Вызывается конструктор
delete rh2; // Вызывается деструктор (~ResourceHolder()), затем освобождается память
return 0;
}
Важные правила:
- Используйте
deleteдля памяти, выделеннойnew. - Используйте
delete[]для массивов, выделенныхnew[]. - Используйте
free()только для памяти, выделенной функциями семействаmalloc. - Смешивание (
new/freeилиmalloc/delete) приводит к неопределенному поведению (undefined behavior). - В современном C++ предпочтительно использовать умные указатели (
std::unique_ptr,std::shared_ptr) и контейнеры (std::vector), которые автоматически управляют памятью.
Ответ 18+ 🔞
Ну, вот смотри, тут такая тема, которую каждый второй на собеседовании пытается проехать, а потом в коде получается ёперный театр. free() и delete — это как водка и пиво: смешивать можно, но потом будет пиздец, и ты сам от себя охуеешь.
free() — это старый, добрый, тупой как пробка инструмент из C. Выделил память через malloc() — освобождай через free(). Он просто отдаёт операционке кусок памяти обратно и всё. Никаких тебе нежностей в виде вызова деструкторов. Просто взял и выкинул, как пустую бутылку в кусты.
delete — это уже наш, цивилизованный C++шный оператор. Он не просто память освобождает. Он сначала аккуратно так говорит объекту: «Дружище, ты своё отъебал, вызывай деструктор, закрывай файлы, чисти за собой хвосты». И только потом уже освобождает память.
Вот смотри на примере, тут всё станет ясно, как божий день:
#include <cstdlib>
class ResourceHolder {
int* data;
public:
ResourceHolder() { data = new int[100]; std::cout << "Resource allocatedn"; }
~ResourceHolder() { delete[] data; std::cout << "Resource freedn"; }
};
int main() {
// Способ первый, криворукий. Делаем по-деревенски.
ResourceHolder* rh1 = (ResourceHolder*)malloc(sizeof(ResourceHolder));
// Конструктор-то не вызвался! Объект как сырой кусок мяса лежит. Память выделена, а `data` — хуй с горы, мусор.
free(rh1); // И тут деструктор не вызовется! У нас же `free()`, ей похуй. В итоге массив `data` так и висит в памяти — вечная утечка. Красота, да?
// Способ второй, правильный. Делаем как взрослые.
ResourceHolder* rh2 = new ResourceHolder(); // Всё, конструктор отработал, память под массив выделена.
delete rh2; // А вот тут сначала вызовется деструктор (~ResourceHolder()), который почистит массив, а потом уже освободится память под сам объект.
return 0;
}
Короче, правила простые, их надо выжечь на подкорке:
- Что выделил через
new— убивай черезdelete. - Что выделил через
new[](массив) — убивай черезdelete[]. Перепутаешь — будет тебе не undefined behavior, а конкретная хиросима в рантайме. - Что выделил через
malloc/calloc/realloc— освобождай черезfree(). - Начинаешь мешать — получаешь неопределённое поведение, а это хуже, чем просто краш. Это когда вроде работает, а потом в пятницу вечером у заказчика всё накрывается медным тазом.
- А самый правильный совет в 2023-м (ой, то есть в наше время) — вообще не ебаться с этим вручную. Бери
std::unique_ptr,std::vectorи живи спокойно. Пусть компилятор сам за тебя думает, гдеdeleteвызывать.