Bỏ qua để đến nội dung

Nhầm lẫn delete và delete[]

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 delete

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ần
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.

new[] phải đi kèm delete[], new (không mảng) phải đi kèm delete - 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ên std::vector hoặc std::unique_ptr<T[]>