Một biến tham chiếu là một bí danh, nghĩa là một tên khác của một biến đã tồn tại. Khi một tham chiếu được khởi tạo với một biến, tên biến hoặc tên tham chiếu có thể được sử dụng để tham chiếu đến biến.
Tóm Tắt
Tham chiếu so với Con trỏ
Tham chiếu thường bị nhầm lẫn với con trỏ nhưng có ba điểm khác biệt chính giữa tham chiếu và con trỏ là như sau:
-
Bạn không thể có tham chiếu NULL. Bạn phải luôn có thể giả định rằng một tham chiếu được kết nối với một phần hợp lệ của bộ lưu trữ.
-
Khi một tham chiếu được khởi tạo cho một đối tượng, nó không thể được thay đổi để tham chiếu đến một đối tượng khác. Con trỏ có thể được trỏ đến một đối tượng khác bất cứ lúc nào.
-
Khi ta tạo tham chiếu thì nó phải được khởi tạo. Con trỏ có thể được khởi tạo bất kỳ lúc nào.
Tạo tham chiếu trong C++
Hãy coi một tên biến như một nhãn gắn với vị trí của biến đó trong bộ nhớ. Sau đó, ta có thể coi một tham chiếu như một nhãn thứ hai được gắn vào vị trí bộ nhớ đó. Do đó, bạn có thể truy cập nội dung của biến thông qua tên biến ban đầu hoặc tham chiếu. Ví dụ:
int i = 17; double d = 20;
Ta có thể khai báo các biến tham chiếu cho i như sau.
int& r = i; double& s = d;
& đặt sau int thể hiện việc khai báo tham chiếu, cụ thể “r là tham chiếu số nguyên được khởi tạo thành i” và “s là tham chiếu double được khởi tạo thành d”. Ví dụ sau sử dụng các tham chiếu trên kiểu int và double:
#include <iostream
> using namespace std; main(){ // khai báo các biếnint
i;double
d; // khai báo các biến tham chiếuint
& r = i;double
& s = d; i =5
; cout <<"Gia tri cua i: "
<< i << endl; cout <<"Gia tri cua tham chieu i: "
<< r << endl; d =11.7
; cout <<"Gia tri cua d: "
<< d << endl; cout <<"Gia tri cua tham chieu d: "
<< s << endl;return
0
; }
Khi đoạn mã trên được biên dịch cùng nhau và được thực thi, nó sẽ tạo ra kết quả sau:
Gia tri cua i: 5 Gia tri cua tham chieu i: 5 Gia tri cua d: 11.7 Gia tri cua tham chieu d: 11.7
Tham chiếu thường được sử dụng cho danh sách đối số hàm và giá trị trả về của hàm. Sau đây là hai chủ đề quan trọng liên quan đến tham chiếu trong C++ mà một lập trình viên C++ cần phải nắm rõ:
Tham chiếu dưới dạng tham số
Dưới đây là một ví dụ về lời gọi theo tham chiếu sử dụng tham chiếu trong C++:
#include <iostream
> using namespace std; // khai báo hàmvoid
swap(int
& x,int
& y); main() { // khai báo các biến local:int
a =100
;int
b =200
; cout <<"Truoc khi swap, a = "
<< a << endl; cout <<"Truoc khi swap, b = "
<< b << endl; /* gọi một hàm để swap các giá trị.*/ swap(a, b); cout <<"Sau khi swap, a = "
<< a << endl; cout <<"Sau khi swap, b = "
<< b << endl;return
0
; } // định nghĩa hàm để swap các giá trị.void
swap(int
& x,int
& y) {int
temp; temp = x; /* lấy giá trị tại địa chỉ x lưu vào temp */ x = y; /* lưu y vào x */ y = temp; /* lưu x vào y (vì temp chứa x) */ }
Kết quả thực thi của đoạn code trên:
Truoc khi swap, a = 100 Truoc khi swap, b = 200 Sau khi swap, a = 200 Sau khi swap, b = 100
Tham chiếu dưới dạng giá trị trả về
Một chương trình C++ có thể dễ đọc và dễ bảo trì hơn bằng cách sử dụng tham chiếu thay vì con trỏ. Một hàm trong C++ có thể trả về một tham chiếu theo cách tương tự như nó trả về một con trỏ.
Khi một hàm trả về một tham chiếu, nó sẽ trả về một con trỏ không tường minh đến giá trị trả về của nó. Bằng cách này, một hàm có thể được sử dụng ở bên trái của một câu lệnh gán. Hãy xét chương trình đơn giản sau:
#include<iostream
> #include<ctime
> using namespace std;double
vals[] = {10.1
,12.6
,33.1
,24.1
,50.0
};double
& setValues(int
i) {return
vals[i]; // trả về một tham chiếu tới phần tử chỉ số i } // hàm main sẽ gọi hàm được định nghĩa ở trên. main() { cout <<"Gia tri truoc khi thay doi:"
<< endl;for
(int
i =0
; i <5
; i++ ) { cout <<"vals["
<< i <<"] = "
<< vals[i] << endl; } setValues(1
) =20.23
; // thay đổi phần tử chỉ số 1 setValues(3
) =70.8
; // thay đổi phần tử chỉ số 3 cout <<"Sau khi thay doi:"
<< endl;for
(int
i =0
; i <5
; i++ ) { cout <<"vals["
<< i <<"] = "
<< vals[i] << endl; }return
0
; }
Khi đoạn mã trên được biên dịch cùng nhau và được thực thi, nó sẽ tạo ra kết quả sau:
Gia tri truoc khi thay doi: vals[0] = 10.1 vals[1] = 12.6 vals[2] = 33.1 vals[3] = 24.1 vals[4] = 50 Sau khi thay doi: vals[0] = 10.1 vals[1] = 20.23 vals[2] = 33.1 vals[3] = 70.8 vals[4] = 50
Khi trả về một tham chiếu, hãy lưu ý rằng đối tượng được tham chiếu không được nằm ngoài phạm vi. Vì vậy, việc trả về một tham chiếu đến biến local là không hợp lệ. Nhưng bạn luôn có thể trả về một tham chiếu trên một biến tĩnh.
int
& func() {int
q; // return q; // lỗi thời gian biên dịchstatic int
x;return
x; // an toàn, x tồn tại ngoài phạm vi }