Cấp phát mảng động trong C++ được thực hiện thông qua 2 toán tử là new và delete. Đây là thao tác quan trọng khi xây dựng các cấu trúc dữ liệu như danh sách liên kết hay cây nhị phân.
1. Cấp Phát Động Là Gì?
Cấp phát động - Dynamic memory allocation trong C/C++ là hình thức xin cấp phát vùng nhớ bởi lập trình viên.
Khi cấp phát động thì người lập trình sẽ chủ động xin cấp phát vùng nhớ khi cần và giải phóng vùng nhớ khi cần thu hồi.
Một số đặc điểm về cấp phát động bạn cần nhớ :
- Vùng nhớ sử dụng khi cấp phát động là vùng nhớ heap
- Lập trình viên cần giải phóng vùng nhớ để tránh rò rỉ bộ nhớ (leak memory)
- Cấp phát động là thao tác chính để tạo nên các cấu trúc dữ liệu như cây nhị phân hay danh sách liên kết
2. Toán Tử New Và Delete
Toán tử new :
Vùng nhớ cấp phát động được xin cấp phát thông qua toán tử new, theo sau sẽ là kiểu dữ liệu. Trong trường hợp bạn xin cấp phát nhiều hơn 1 phần tử thì cần thêm số lượng phần tử trong đóng mở ngoặc vuông.
Toán tử new sẽ trả về con trỏ tới ô nhớ đầu tiên của vùng nhớ được cấp phát hoặc sẽ trả về con trỏ NULL nếu không cấp phát đủ bộ nhớ
Cú pháp :
pointer = new data_type [num_of_elements]
Cú pháp thứ nhất sẽ xin cấp phát 1 phần tử còn cú pháp thứ 2 xin cấp phát 1 khối (tương tự như 1 mảng các phần tử).
Sau khi xin cấp phát 1 mảng động thì bạn có thể sử dụng mảng động thông qua con trỏ pointer tương tự như mảng 1 chiều.
Mã nguồn :
using namespace std;
int main() {
int *ptr = new int[5];
cout << "Gia tri cua ptr : " << ptr << endl;
ptr[0] = 1;
ptr[1] = 2;
ptr[2] = 3;
ptr[3] = 4;
ptr[4] = 5;
for (int i = 0; i < 5; i++) {
cout << ptr[i] << ' '; // hoac *(ptr + i)
}
}
Output :
1 2 3 4 5
Trong trường hợp vùng nhớ heap không đủ cấp phát thì chương trình sẽ ném ra ngoại lệ và trả về con trỏ NULL. Bạn có thể kiểm tra việc cấp phát có thành công hay không, trong ví dụ dưới đây mình sẽ in cấp phát vùng nhớ có cỡ 1013 phần tử int để việc cấp phát không thành công.
using namespace std;
int main() {
int *ptr = new int[10000000000000ll];
return 0;
}
Output :
what(): std::bad_alloc
Để tránh chương trình ném ra ngoại lệ bạn có thể dùng thêm cơ chế nothrow để kiểm nghiệm việc ptr sẽ là NULL nếu không đủ bộ nhớ cấp phát
using namespace std;
int main() {
int *ptr = new(nothrow) int[10000000000000ll];
if (ptr == NULL) {
cout << "Khong du bo nho cap phat !\n";
}
return 0;
}
Output :
Toán tử delete :
Toán tử delete được sử dụng để giải phóng vùng nhớ đã xin cấp phát trước đó bở toán tử new.
Việc này là cần thiết để tránh việc leak memory
Cú pháp :
delete [] pointer;
Cú pháp thứ nhất để giải phóng vùng nhớ 1 phần tử được cấp phát trước đó còn cú pháp thứ 2 dùng khi bạn đã xin cấp phát 1 mảng các phần tử.
Mã nguồn :
using namespace std;
int main() {
int n;
cout << "Nhap so luong phan tu xin cap phat : ";
cin >> n;
int *ptr = new(nothrow) int[n];
if (ptr == NULL) {
cout << "Khong du bo nho cap phat !\n";
} else {
cout << "Nhap cac phan tu trong day : ";
for (int i = 0; i < n; i++) {
cin >> ptr[i];
}
cout << "Cac phan tu vua nhap : ";
for (int i = 0; i < n; i++) {
cout << ptr[i] << ' ';
}
delete []ptr;
}
return 0;
}