Cả delete và free() đều dùng để giải phóng bộ nhớ động, nhưng chúng không thể thay thế lẫn nhau.
Quy tắc vàng
| Cấp phát bằng | Giải phóng bằng |
|---|---|
new / new[] | delete / delete[] |
malloc() / calloc() / realloc() | free() |
Sử dụng sai cặp (ví dụ delete cho con trỏ từ malloc) gây hành vi không xác định (undefined behavior).
Ví dụ minh họa đúng/sai
#include <cstdlib> // malloc, free
#include <new> // bad_alloc
int main() {
int x = 10;
int* ptr1 = &x; // Trỏ đến biến stack
int* ptr2 = (int*)malloc(sizeof(int)); // Heap qua C
int* ptr3 = new int; // Heap qua C++
int* ptr4 = nullptr; // Con trỏ null
// --- SAI ---
delete ptr1; // LỖI NGHIÊM TRỌNG: ptr1 không phải từ new
delete ptr2; // LỖI: ptr2 từ malloc, phải dùng free()
// --- ĐÚNG ---
delete ptr3; // OK: ptr3 từ new
delete ptr4; // OK: delete nullptr an toàn (không làm gì)
// free() cho malloc
free(ptr2); // OK
// free(nullptr) cũng an toàn
free(nullptr);
return 0;
}
Sự khác biệt quan trọng
| Đặc điểm | delete | free() |
|---|---|---|
| Gọi destructor? | CÓ (cho object) | KHÔNG |
| Overload được? | CÓ (operator delete) | KHÔNG |
| Xử lý mảng? | Cần delete[] | Chỉ free() (programmer tự quản lý size) |
| An toàn với nullptr? | CÓ | CÓ |
Lưu ý về delete[]
Luôn dùng delete[] cho mảng được cấp phát bằng new[]. Dùng delete (không có ngoặc vuông) cho mảng sẽ chỉ gọi destructor cho phần tử đầu tiên → rò rỉ bộ nhớ/hủy không hoàn chỉnh.
int* arr = new int[100];
delete[] arr; // ĐÚNG
// Sai:
delete arr; // Chỉ hủy arr[0], rò rỉ 99 phần tử còn lại
Thực hành hiện đại (Modern C++)
Thay vì quản lý thủ công, hãy dùng smart pointer:
std::unique_ptr<T>- sở hữu độc quyền.std::shared_ptr<T>- sở hữu chia sẻ.std::make_unique<T>(),std::make_shared<T>()- an toàn exception.
Với container, dùng std::vector, std::string thay vì mảng động thô.