Hiểu về con trỏ trong C/C++ phần 1

2018-07-20

Content:

Trước khi vào vấn đề, định nghĩa một cấu trúc “node” trước:

1
2
3
4
5
struct ListNode {
  int value;
  ListNode* next;
  ListNode(x): value(x), next(NULL) {}
};

Với cấu trúc trên, chúng ta có thể tạo ra 3 nodes như thế này:

1
2
3
ListNode* head = new ListNode(1);
ListNode* node2 = new ListNode(2);
ListNode* node3 = new ListNode(3);

Cùng giải thích rõ hơn ý nghĩa của lệnh gán trên:

  • Toán tử new ListNode(1) sẽ cấp phát bộ nhớ trên HEAP, và trả về một giá trị là địa chỉ của vùng nhớ này.
  • ListNode* head: khai báo một biến con trỏ trỏ đến kiểu dữ liệu ListNode, biến con trỏ này được lưu trên bộ nhớ STACK.
  • Lệnh gán ListNode* head = new ListNode(1): gán một giá trị địa chỉ (của bộ nhớ) cho một con trỏ; lệnh gán liên quan đến con trỏ thường có dạng vế trái là một con trỏ, vế phải là địa chỉ X của một vùng nhớ nào đó; như vậy lệnh gán có thể được hiểu là: con trỏ head trỏ đến vùng nhớ có địa chỉ là X, vùng nhớ này lưu ListNode(1).

Hình vẽ minh hoạ:


Hình 1. Cách các nodes được cấp phát trên bộ nhớ.

Tiếp theo, liên kết 3 nodes này lại với nhau để tạo thành danh sách liên kết đơn:

1
2
head->next = node2;
node2->next = node3;

Các lệnh gán trên cũng được giải thích hoàn toàn tương tự (chúng ta sẽ nhận thấy rằng về bản chất lệnh này với lệnh cấp phát bên trên là một):

  • head là biến con trỏ trên STACK, con trỏ này trỏ đến bộ nhớ trên HEAP thuộc kiểu ListNode chứa biến value=1next=NULL, vậy head->next chính là biến con trỏ next trên HEAP.
  • Lệnh head->next = node2 có vế trái là một con trỏ, vế phải là địa chỉ của vùng nhớ trên HEAPnode2 đang trỏ tới (value=2next=NULL). Như phân tích ở trên, lệnh gán này sẽ làm con trỏ head-next trỏ tới vùng nhớ có địa chỉ node2.

Phân tích tương tự cho lệnh con lại, ta có hình minh hoạ sau đây:


Hình 2. Cách các nodes liên kết tạo thành danh sách đơn.

Happy coding,