一.定義:
引用就是某一變數(目標)的一個別名,對引用的操作與對變數直接操作完全一樣.
二.用法:
- 基本用法
例如: int & a = b;
- 引用作為函式返回值
先看一個例子:
1 #include <iostream> 2 using namespace std; 3 class Node{ 4 int x; 5 public: 6 Node(const Node & n){//去掉copy函式關於h的輸出結果神奇般相同,原因未知 7 x = n.x; 8 } 9 Node(int x=0):x(x){ 10 11 } 12 }; 13 int temp ; 14 int & F(){ 15 temp*=2; 16 return temp; 17 } 18 int F1(){ 19 temp*=2; 20 return temp; 21 } 22 Node F2(){ 23 Node u(5); 24 cout << &u << " "; 25 return u; 26 } 27 int main(){ 28 temp = 5; 29 int &d = F(); //引用給引用,他們地址相同 30 int e = F(); //引用給非引用,發生了複製 31 const int & f = F();//把引用值賦值給常引用,他們的地址相同 32 const int & g = F1();//對於內建資料型別,把非引用值賦值給常引用,他們的地址不同 33 cout << &d << " " << &temp << endl; 34 cout << &e << " " << &temp << endl; 35 cout << &f << " " << &temp << endl; 36 cout << &g << " " << &temp << endl; 37 const Node & h = F2();//對於類物件型別,把非引用值賦值給常引用,他們的地址可能不同 38 cout << &h << endl; 39 cout << d << " " << temp << endl; 40 return 0; 41 }
-
程式輸出結果為:
0x602194 0x602194
0x7fffe0565418 0x602194
0x602194 0x602194
0x7fffe056541c 0x602194
0x7fffe0565410 0x7fffe0565410
80 80從結果中可以看到,當使用引用作為程式返回值並且將這個返回值賦值給引用型別時,他們的地址是相同的(都指向temp這個變數),其他情況都產生了值的賦值,發生了地址的變化。由此也可以看出,使用引用可以減少值的複製,特別是當需要傳的資料特別大的時候。
- 另外,函式中返回非引用類物件賦值給const 引用變數時輸出結果有些奇怪,不明白裡面的copy函式為什麼不呼叫但只加上就可以使他們的地址相同。
- 常引用
基本用法如下:
int b = 4; const int a = b;
使用常引用可以是引用的值不可修改。這樣可以防止因誤操作引發的資料修改,保證了安全性。
- 引用函式作為左值
一般非引用函式都是隻能作為右值,函式一旦計算完成那麼它就是一個確定的常數。但引用函式不同。它既可作為左值,又可作為右值。
int &d = ++F();
相當於
int A[10]; int &array = A;
這是它作為左值的應用。
但當我執行
int &d = F()++;
這樣會產生錯誤。錯誤資訊為:
error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
這個錯誤資訊與執行
int &d = 5;
的錯誤資訊一致,說明F()++操作實際上是相當於先把F()的值存到一個整型常量中,然後F()(相當於temp)的值加一.一個整型常量無法複製給int&型別。
執行
const int &d = F()++;(使用常引用)
或
int d = F()++;(把常量值拷貝到變數中)
才可以正常編譯。
三.注意事項:
- 引用不能用於陣列,但可以用在指標上
如果嘗試執行
int A[10]; int &array = A;
編譯器會報錯:
error: declaration of 'd' as array of references但我可以對指標用引用:
int *p = A; int &array = p;
編譯成功。
至於為什麼不能對陣列用引用,網上答案很多,我自己不能確定哪種答案是正確的,大家可以自行搜尋相關問題。
- 不要試圖返回臨時物件的引用,這樣引用會成為無效引用,假如把返回值賦值給變數,那麼程式可能會崩掉
- 返回函式內部new分配的記憶體的引用或指標,這樣的寫法不推薦,很容易會造成記憶體洩漏(即無法正常的回收這塊記憶體)
- 注意常引用與普通引用之間的相互賦值問題
1 temp = 5; 2 const int t = 6; 3 int &d = temp; 4 const int &e = temp; 5 const int &f = t; 6 int &g = t;//編譯錯誤
常量變數都可以賦值給常引用,但只有變數值才可以給普通引用,若常量值給普通引用會發生編譯錯誤。
- 另外記錄一次在寫C++作業的過程中偶然發現的一個問題,這加深了我對常引用以及ostream過載等的一些理解。點選跳轉