close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

Sự khác biệt giữa toán tử delete và delete[] trong C++

Trong bài viết này, chúng ta sẽ tìm hiểu về sự khác biệt giữa toán tử delete và delete[]. Cũng như, việc sử dụng pha trộn giữa new[] và delete có thể gây ra hiện tượng rò rỉ bộ nhớ (memory leak).

Để cấp phát bộ nhớ động trên heap, ta sử dụng toán tử new[] như sau:

Sample;
Sample * ptrArr = new Sample[5];

Ở đây new[] sẽ thực hiện các hoạt động nội bộ bên trong sau:

  1. Đầu tiên, nó sẽ cấp phát bộ nhớ trên heap tương đương với kích thước của 5 đối tượng của lớp Sample bằng cách gọi toán tử new [].
  2. Bước thứ hai, nó gọi hàm tạo mặc định cho mỗi đối tượng được cấp phát, tức là 5 Đối tượng trong trường hợp này.

Để xóa bộ nhớ được cấp phát bởi toán tử new[], chúng ta không nên sử dụng toán tử delete vì toán tử này một cách nội bộ sẽ gọi toán tử xóa để hủy cấp phát bộ nhớ và chỉ gọi hàm hủy của 1 đối tượng. Hàm hủy của 4 đối tượng còn lại sẽ không được gọi trong trường hợp này, mặc dù bộ nhớ được hủy cấp phát. Điều này có thể làm phát sinh vấn đề rò rỉ bộ nhớ.

Hãy thử kiểm tra ví dụ sau để biết rò rỉ bộ nhớ bằng cách trộn new[] và delete,

class Sample
{
    int * m_ptr;
public:
    Sample()
    {
        std::cout<<"Sample::Constructor\n";
        m_ptr = new int();
    }
    ~Sample()
    {
        std::cout<<"Sample::Destructor\n";
        delete m_ptr;
        m_ptr = NULL;
    }
};
int main()
{
    Sample * ptrArr = new Sample[5];
    // Gọi delete trên con trỏ mà có chứa bộ 
    // nhớ được cấp phát bởi new[] sẽ chỉ có
    // một hàm hủy được gọi, 4 cái còn lại
    // thì không, gây ra rò rỉ bộ nhớ.
    delete ptrArr;
    return 0;
}

Ở đây 5 đối tượng của lớp Sample đã được phân bổ trên heap bởi new[]. Nhưng vì toán tử delete được sử dụng để xóa bộ nhớ được cấp phát bởinew[], do đó hàm hủy của chỉ một đối tượng được gọi. Đối với 4 đối tượng còn lại, hàm hủy không được gọi, do đó m_ptr không bị xóa đối với các đối tượng còn lại và do đó dẫn đến rò rỉ bộ nhớ.

Làm sao để khắc phục tình trạng rò rỉ bộ nhớ do trộn new[] và delete?

Chúng ta nên luôn sử dụng toán tử delete[] với toán tử new[] để xóa mảng được cấp phát động trên heap. Toán tử delete[] thực hiện các hoạt động sau trong nội bộ như sau:

  1. Trong bước đầu tiên, nó gọi hàm hủy cho mỗi đối tượng được cấp phát, tức là 5 Đối tượng trong trường hợp này.
  2. Trong bước thứ hai, nó sẽ khử cấp phát / xóa bộ nhớ khỏi heap tương đương với kích thước của 5 Đối tượng của lớp Sample bằng cách gọi toán tử delete[].

Giờ, hãy sửa lỗi rò rỉ bộ nhớ ở trên bằng toán tử delete[],

#include <iostream>
class Sample
{
    int * m_ptr;
public:
    Sample()
    {
        std::cout<<"Sample::Constructor\n";
        m_ptr = new int();
    }
    ~Sample()
    {
        std::cout<<"Sample::Destructor\n";
        delete m_ptr;
        m_ptr = NULL;
    }
};
int main()
{
    Sample * ptrArr = new Sample[5];
    // Sẽ gọi hàm hủy của cả 5 đối tượng.
    delete [] ptrArr;
    return 0;
}


Đã đăng vào

trong

bởi

Thẻ:

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *