[Basic] Cấp phát bộ nhớ động và tham chiếu trong C++

Cấp phát bộ nhớ động

Con trỏ là biến lưu địa chỉ của 1 vùng trong bộ nhớ. Trước khi sử dụng con trỏ ta phải gán địa chỉ 1 vùng nhớ cho con trỏ. Khi đó con trỏ có thể thao tác trực tiếp với giá trị trên vùng nhớ đó (lấy giá trị, update giá trị).

Ở các bài trước chúng ta thường gán địa chỉ của 1 biến có sẵn cho biến con trỏ.

Ví dụ:

int x = 10;

int* ptr = &x; 

=> Khi đó biến con trỏ sẽ trỏ đến địa chỉ biến x. x thay đổi giá trị thì *ptr cũng thay đổi theo và ngược lại.

Một cách khác ta có thể cấp phất 1 địa chỉ hoàn toàn mới cho biến con trỏ. Khi đó con trỏ sẽ trỏ vào địa chỉ của riêng nó mà không phải dùng chung.

Để cấp phát bộ nhớ cho con trỏ ta sử dụng toán tử new

Ví dụ:

 
int* ptr = new int; 

int* arr = new int[5]; 

Trong bài Mảng, ta đã biết số phần tử của mảng là cố định không thể thay đổi và phải khai báo trước. Điều đó khá bất tiện khi ta khai báo trước có thể thừa hoặc thiếu phần tử. Lúc này con trỏ sẽ được thay thế cho mảng. Ta có thể cấp phát số phần tử cho con trỏ 1 cách linh động, dùng bao nhiêu cấp phát bấy nhiêu.

Ví dụ:

#include <iostream>

using namespace std;

int main()
{

   int length;

   cout << "Enter number : ";

   cin >> length;

   int* arr = new int[length];

   //Gán giá trị cho từng phần tử
   for (int i = 0; i < length; i++)
   {

      *(arr + i) = i * 2;
 
   }

   //In các giá trị 

   for (int i = 0; i < length; i++)
   {

      cout << "arr["<< i << "] = " << *(arr + i) <<endl;

   }

   return 0;

}

Kết quả:

Enter number : 5
arr[0] = 0
arr[1] = 2
arr[2] = 4
arr[3] = 6
arr[4] = 8

Chú ý:

Nếu không cấp phát được bộ nhớ cho con trỏ toán tử new sẽ ném ra exception std::bad_alloc

=> Để new trả về null khi không cấp phát được bộ nhớ ta sử dụng std::nothrow

Ví dụ:

#include <iostream> 

using namespace std;

int main() 
{
 
   int* arr = new (std::nothrow) int[5];
 
   if (arr != nullptr)
   {
 
      //TODO
 
   }
 
   return 0;

}

Khởi tạo giá trị cấp phát động

Khi cấp phát bộ nhớ cho con trỏ, tại địa chỉ được cấp phát đó sẽ có giá trị “rác”. Ta có thể khởi tạo giá trị lúc cấp phát.

Ví dụ:

int* ptr = new int(); //Khởi tạo giá trị 0

int* ptr1 = new int(5); //Khởi tạo giá trị 5

int* arr = new int[5](); //Khởi tạo tất cả các phần tử có giá trị 0

int* arr1 = new int[4]{1,2,3,4}; //Khởi tạo giá trị các phần tử

Giải phóng bộ nhớ

Bộ nhớ được cấp phát động cho con trỏ, khi không dùng nữa ta phải giải phóng để tránh memory leak.

Để giải phóng bộ nhớ cấp phát cho 1 phần tử ta dùng toán tử delete.

Giải phóng bộ nhớ cấp phát cho 1 mảng ta dùng toán tử delete[]

Ví dụ

int* ptr = new int;

delete ptr;

ptr = nullptr;

int* arr = new int[10];

delete[] arr;

arr = nullptr;

Chú ý:

Sau khi giải phóng bộ nhớ nên gán giá trị null cho con trỏ, để đảm báo rằng con trỏ không trỏ vào địa chỉ nào.

So sánh malloc và new

newmalloc
Là toán tử cấp phát bộ nhớ động trong C++Là hàm cấp phát bộ nhớ động C
Trả về con trỏ có kiểu dữ liệu được cấp phát.Trả về con trỏ void*, phải ép kiểu sang kiểu dữ liệu cần cấp phát
Ném ra ngoại lệ (exception std::bad_alloc ) khi không cấp phát được bộ nhớTrả về null khi không cấp phát được bộ nhớ
Gọi hàm tạo (contructor ) của đối tượngKhông gọi hàm tạo (constructor) của đối tượng
Không thay đổi kích thước vùng nhớ cấp phát bởi newCó thể sử dụng calloc để thay đổi kích thước vùng nhớ được cấp phát
Sử dụng delete, delete[] để giải phóng bộ nhớSử dụng hàm free() để giải phóng bộ nhớ

Chú ý:

  • Không sử dụng hàm free() để giải phóng bộ nhớ được cấp phát bởi new.
  • Không sử dụng delete để giải phóng bộ nhớ được cấp phát bới malloc.

Tham chiếu trong C++

Có thể hiểu tham chiếu là tên gọi khác của 1 biến đã tồn tại.

Ví dụ

#include <iostream> 

using namespace std;

int main() 
{

   int val = 20;

   //Định nghĩa biến refVal tham chiếu đến val
   int& refVal = val;

   cout << "refVal = " << refVal << endl;

   refVal = 50;

   cout << "val = " << val << endl;

   return 0;

}

Kết quả

refVal = 20
val = 50

Chú ý:

  • Phải luôn khởi tạo khi khai báo tham chiếu.

Ví dụ:

int& ref; //Error vì không khởi tạo
  • Không thể tham chiếu đến NULL

Ví dụ :

int& ref = NULL; //Error
  • Khi 1 tham chiếu được khởi tạo cho 1 đối tượng không thể thay đổi để tham chiếu tới đối tượng khác.

Was this article helpful?

Có 1 bình luận

  1. It’s really a great and useful piece of information.
    I am happy that you just shared this helpful information with us.

    Please keep us informed like this. Thanks for sharing.

Leave A Comment?