Nhầm lẫn delete và delete[]
Vấn đề
Phần tiêu đề “Vấn đề”Bài “Cấp phát bộ nhớ động” đã đề cập ngắn gọn: bộ nhớ cấp phát bằng new[] (mảng) phải giải phóng bằng delete[], không phải delete thường. Dùng sai là undefined behavior - và đây là một trong những lỗi dễ gõ nhầm nhất khi mới học C++.
int* single = new int(42);int* array = new int[10];
delete single; // ĐÚNG - single được cấp phát bằng new (không có [])delete[] array; // ĐÚNG - array được cấp phát bằng new[]
// delete array; // SAI! new[] phải đi với delete[]// delete[] single; // CŨNG SAI! new (không có []) phải đi với deleteVì sao dùng sai lại nguy hiểm?
Phần tiêu đề “Vì sao dùng sai lại nguy hiểm?”Khi cấp phát một mảng bằng new[], trình biên dịch thường lưu thêm thông tin về số lượng phần tử ngay trước vùng dữ liệu thực tế, để delete[] biết cần gọi destructor cho bao nhiêu phần tử (quan trọng với mảng đối tượng có destructor tùy chỉnh). Dùng delete (không có []) trên một mảng khiến chương trình chỉ gọi destructor cho phần tử đầu tiên, và cách bộ nhớ được “trả lại” cho hệ thống cũng có thể không đúng cách - dẫn đến rò rỉ bộ nhớ hoặc crash tùy vào cách cài đặt trình biên dịch.
struct Resource { Resource() { std::cout << "Tao Resource" << std::endl; } ~Resource() { std::cout << "Huy Resource" << std::endl; }};
Resource* resources = new Resource[3];// Tao Resource (x3)
delete resources; // SAI! Chỉ gọi ~Resource() cho MỘT phần tử, 2 phần tử còn lại "rò rỉ" và không được huỷ đúng cách// Huy Resource (chỉ 1 lần, thay vì 3 lần như mong đợi)Giải pháp: tránh dùng new[]/delete[] trực tiếp
Phần tiêu đề “Giải pháp: tránh dùng new[]/delete[] trực tiếp”Đây là lý do C++ hiện đại gần như luôn khuyến khích dùng std::vector hoặc std::unique_ptr<T[]> thay vì tự quản lý mảng động bằng new[]/delete[]:
#include <vector>#include <memory>
std::vector<int> numbers(10); // Không cần lo lắng về delete[] - tự động quản lý
std::unique_ptr<int[]> arr = std::make_unique<int[]>(10); // Cũng tự động gọi delete[] đúng cách khi cầnQuy tắc ghi nhớ
Phần tiêu đề “Quy tắc ghi nhớ”| Cấp phát | Giải phóng |
|---|---|
new T |
delete ptr; |
new T[n] |
delete[] ptr; |
Luôn dùng đúng cặp tương ứng - không bao giờ trộn lẫn.
Tóm tắt
Phần tiêu đề “Tóm tắt”
new[]phải đi kèmdelete[],new(không mảng) phải đi kèmdelete- trộn lẫn là undefined behavior, thường gây rò rỉ bộ nhớ hoặc gọi destructor không đầy đủ.
- Cách an toàn nhất là tránh dùng
new[]/delete[]trực tiếp - ưu tiênstd::vectorhoặcstd::unique_ptr<T[]>