Menu
CoddyTech

Bộ nhớ ngăn xếp và heap

Thuộc phần Lập trình hướng đối tượng trong hành trình C++ của Coddy. Bài học 12 trên 104.

Chương trình C++ sử dụng hai vùng bộ nhớ chính: stack và heap. Hiểu rõ các đối tượng nằm ở đâu là điều rất quan trọng để viết code hiệu quả và không có bug.

Stack là vùng nhớ tự động, có tốc độ nhanh. Các biến được khai báo bên trong hàm nằm ở đây và tự động bị hủy khi ra khỏi phạm vi.

void example() {
    int x = 10;           // Cấp phát trên ngăn xếp
    Player player;        // Cấp phát trên ngăn xếp, tự động bị hủy
}   // x và player bị hủy tại đây

Heap là vùng bộ nhớ lớn hơn nhưng chậm hơn, do bạn tự quản lý. Các đối tượng trong heap tồn tại cho đến khi bạn chủ động xóa chúng.

void example() {
    Player* player = new Player();  // Cấp phát bộ nhớ trên heap
    // player tồn tại cho đến khi bị xóa
    delete player;                   // Cần giải phóng bộ nhớ thủ công
}

Điểm khác biệt chính:

Ngăn xếpHeap
Cấp phát nhanhCấp phát chậm hơn
Kích thước giới hạnSức chứa lớn
Tự động dọn dẹpCần dọn dẹp thủ công
Đối tượng có kích thước cố địnhĐối tượng có kích thước động

Dùng cấp phát trên ngăn xếp cho các đối tượng nhỏ, có thời gian tồn tại ngắn. Dùng cấp phát trên heap khi đối tượng cần tồn tại lâu hơn phạm vi của nó hoặc khi kích thước của đối tượng được xác định lúc chạy.

Quên giải phóng bộ nhớ heap sẽ gây ra rò rỉ bộ nhớ, một nguyên nhân phổ biến gây lỗi trong các chương trình C++.

challenge icon

Thử thách

Dễ

Hãy tìm hiểu sự khác biệt giữa bộ nhớ stack và heap bằng cách tạo một lớp Counter đơn giản, theo dõi thời điểm các đối tượng được tạo và hủy.

Bạn sẽ tạo hai tệp để sắp xếp code:

  • Counter.h: Định nghĩa lớp Counter với thuộc tính name riêng tư (chuỗi). Thêm hàm khởi tạo nhận một tên và in ra "Creating: <name>", cùng hàm hủy in ra "Destroying: <name>". Thêm phương thức getName() để trả về tên của bộ đếm.
  • main.cpp: Minh họa cách cấp phát trên stack và heap. Đọc một tên từ đầu vào, sau đó:
    • Tạo một Counter được cấp phát trên stack bằng tên đó
    • Tạo một Counter được cấp phát trên heap với tên "HeapCounter"
    • In tên của cả hai bộ đếm theo định dạng "Stack: <name>" và "Heap: <name>"
    • Xóa bộ đếm được cấp phát trên heap để tránh rò rỉ bộ nhớ

Quan sát thứ tự xuất hiện của thông báo từ hàm khởi tạo và hàm hủy thay đổi tùy theo thời điểm bạn tạo và xóa từng đối tượng. Đối tượng trên stack sẽ tự động bị hủy khi main() kết thúc, còn bạn phải xóa đối tượng trên heap một cách tường minh.

Đưa tệp tiêu đề vào main.cpp bằng #include "Counter.h".

Tự làm thử

#include <iostream>
#include <string>
#include "Counter.h"

using namespace std;

int main() {
    // Đọc tên từ đầu vào
    string inputName;
    cin >> inputName;

    // TODO: Tạo một Counter trên stack bằng inputName

    // TODO: Tạo một Counter trên heap với tên "HeapCounter"

    // TODO: In ra tên của Counter trên stack theo định dạng "Stack: <name>"

    // TODO: In ra tên của Counter trên heap theo định dạng "Heap: <name>"

    // TODO: Xóa Counter trên heap để tránh rò rỉ bộ nhớ

    return 0;
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C++ online