I. Địa chỉ của biến trong máy tính
1. Điều gì xảy ra khi khai báo một biến?
Đúng, khi ta muốn sử dụng một biến với kiểu dữ liệu nguyên thủy, ta cần khai báo biến đó trước. Sau khi biến được khai báo, hệ điều hành sẽ tìm một vùng nhớ trống trên các thiết bị lưu trữ tạm thời của máy tính (như RAM, ngăn xếp hoặc các vùng lưu trữ khác). Nếu tìm được một vùng nhớ có đủ khoảng trống cho kích thước của biến, thì biến sẽ nắm giữ vùng nhớ đó.
Sau khi một vùng nhớ đã được cấp phát cho biến, chương trình có thể biết chính xác vị trí của biến đó trên bộ nhớ để thực hiện các lệnh với biến. Mỗi biến sau khi được khai báo sẽ có một địa chỉ vùng nhớ trên thiết bị lưu trữ mà biến đó đang được lưu trữ.
2. Địa chỉ của biến
Các thiết bị nhớ tạm thời (RAM) được tạo nên bởi các ô nhớ liên tiếp nhau, trong đó mỗi ô nhớ tương ứng với một byte và có một số thứ tự đại diện cho vị trí của ô nhớ đó trong thiết bị. Số thứ tự này được gọi là địa chỉ của ô nhớ.
Các địa chỉ của ô nhớ là những con số ảo được tạo ra bởi hệ điều hành, mà con người rất khó đọc. Hãy tưởng tượng các ô nhớ được đánh số từ 0, 1, và địa chỉ cuối cùng được đánh số tương ứng với số ô nhớ của thiết bị đó.
3. Lấy địa chỉ của một biến trong C++
Để lấy địa chỉ của biến "x" trong các kiểu dữ liệu nguyên thủy, ta chỉ cần thêm toán tử "&" phía trước nó.
Thử chạy chương trình này, ta thu được kết quả là một dãy địa chỉ của biến x đã khai báo:
4. Tham chiếu (Reference)
Trong chủ đề này, chúng ta sẽ tìm hiểu về khái niệm tham chiếu trong C++. Tham chiếu cũng là một loại dữ liệu cơ bản, nó giúp tạo ra một biệt danh khác cho một biến đã tồn tại.
Để tạo một tham chiếu, ta sử dụng toán tử "&" sau kiểu dữ liệu và trước tên biến trong khai báo biến. Một điều quan trọng là biến tham chiếu phải được khởi tạo ngay từ một biến đã tồn tại.
Lấy ví dụ:
Cùng in ra giá trị của hai biến này với đoạn lệnh dưới đây:
Ta thấy kết quả như sau:
Như các bạn thấy, giá trị của hai biến này giống nhau. Tuy nhiên, biến tham chiếu không phải là một bản sao của biến gốc. Hãy in ra địa chỉ của hai biến:
Ta có kết quả:
Có thể thấy, hai biến có chung địa chỉ. Về bản chất, toán tử "&" không có nghĩa là "địa chỉ của", mà nó có nghĩa là "tham chiếu tới". Khi thực hiện tham chiếu từ biến "x" tới biến "x_reference", thì biến "x_reference" sẽ cùng kiểm soát vùng nhớ có địa chỉ là địa chỉ của biến "x".
Nói cách khác, hai biến này là hai tên khác nhau nhưng cùng kiểm soát một địa chỉ vùng nhớ. Điều này có nghĩa là khi bạn thay đổi giá trị của biến "x_reference", giá trị của biến "x" cũng sẽ thay đổi theo và ngược lại. Đây chính là cơ chế của việc truyền tham chiếu trong hàm ở C++.
Lưu ý:
- Một biến tham chiếu chỉ được phép tham chiếu tới một biến cùng kiểu, và sau khi đã tham chiếu thì không thể tham chiếu tới một biến khác.
- Không thể khai báo một biến tham chiếu tới một hằng số, vì hằng số không thể thay đổi trong khi biến tham chiếu có thể, do đó sẽ gây xung đột.
II. Con trỏ trong C++
1. Khái niệm con trỏ (pointer)
Khác với tham chiếu, con trỏ là một biến có địa chỉ độc lập, nhưng giá trị trong vùng nhớ của con trỏ lại chính là địa chỉ của biến mà nó trỏ tới (hoặc một địa chỉ ảo).
Trong ví dụ trên, chúng ta có một biến con trỏ được cấp phát vùng nhớ tại địa chỉ 3255, và nó trỏ đến vùng nhớ có địa chỉ 1224. Điều này có nghĩa là giá trị của nó là 1224 (tất nhiên chỉ là ví dụ để dễ hiểu, trong thực tế các địa chỉ phức tạp hơn nhiều).
2. Khai báo con trỏ
Để khai báo một con trỏ, ta sử dụng thêm toán tử *
trong lời khai báo (không cần thiết phải đặt sát cạnh tên biến)
Tuy nhiên, chúng tôi nên sử dụng cách thứ hai để phân biệt rõ ràng với việc lấy giá trị của một biến con trỏ trong C++ (phần này sẽ được đề cập trong bài về thư viện STL C++).
Khi khai báo một biến con trỏ, biến đó chỉ được phép trỏ vào địa chỉ của các biến cùng kiểu đã khai báo.
Ví dụ, tôi sẽ khai báo một con trỏ kiểu int, thì biến con trỏ này chỉ được phép trỏ vào các địa chỉ của biến kiểu int: