1. 程式人生 > >C++小結--引用

C++小結--引用

1 什麼是引用

引用就是給已知的一個變數起了一個別名,引用引入了物件的一個同義詞。定義引用的表示方法與定義指標相似,只是用&代替了*。引用(reference)是c++對c語言的重要擴充。引用就是某一變數(目標)的一個別名,對引用的操作與對變數直接操作完全一樣。其格式為:型別 &引用變數名 = 已定義過的變數名。

列如:int a = 10; int &b = a; 那麼b也等於10。b和a其實是一塊記憶體。

我們放在具體的程式碼中驗證一下:

#include <iostream>
using namespace std;

int main()
{
    cout
<< "引用測試例子\n"; int a = 123; int &b = a; //引用的實質就是給一個地址起多個別名 注意和指標的區別 //同一塊記憶體空間有兩個變數的名字 a b 改變a b也跟著改變 b = 43; cout << "b = " << b << endl; cout << "&b = " << &b << endl; cout << "&a = " << &a << endl; system("pause"
); return 0; }

輸出結果如下:

引用測試例子
b = 43
&b = 0095FA20
&a = 0095FA20
請按任意鍵繼續. . .

2 引用的特點

1 一個變數可以有多個引用
2 引用必須初始化
3 引用只能在初始化的時候引用一次,不能轉而引用其他的變數。

3 引用的幾種用法

3.1 基礎引用

void fun()  
{  
     int a = 1;  
     int& b = a;  

     cout<<"a:address->" <<&a<< endl;  
     cout
<<"b:address->" <<&b<< endl; a = 2; b = 3; int& c = b;// 引用一個引用變數,別名的別名 c = 4; }

3.2 常量引用

void fun2()  
{  
     int d1 = 4;  
     const int & d2 = d1;  
     d1 = 5;//d1改變,d2的值也會改變。  
     //d2 = 6;//不能給常量(不能被修改的量)賦值。  

     const int d3 = 1;  
     const int & d4 = d3;  
     //int&d5 = d3;  
     const int & d6 = 5;//常量具有常性,只有常引用可以引用常量  

     double d7 = 1.1;  
     //int& d8 = d7;//d7是double型別,d8是int,d7賦值給 d8時要生成一個臨時變數  
                   //也就是說d8引用的是這個帶有常性的臨時變數,所以不能賦值。  
     const int& d9 = d7;  
} 

3.3 引用作為引數

這裡引用作為引數和傳址呼叫相似,我們 舉個交換兩個數的例子來說明一下。

1.【值傳遞】如果形參為非引用的傳值方式,則生成區域性臨時變數接收實參的值
/*值傳遞的方式無法實現交換,因為傳參時對於引數leftright拷貝一臨時副本,交換的是副本值,因為其是臨時變數函式退出,變數銷燬,並不會影響外部leftright的值,所以修改失敗 */  
void Swap (int left, int right) 
{ 
     int temp = left;  
     left = right ;  
     right = temp ;  
}  

2.【引用傳遞】如果形參為引用型別,則形參是實參的別名。
/*使用引用的話,不做臨時拷貝,&的使用說明此處只是原引數的另一個名字而已,所以修改時直接在原引數的基礎上修改變數值,所以交換成功*/  
void Swap (int& left, int& right)  
{  
     int temp = left;  
     right = left ;  
     left = temp ;  
}  

3.【指標傳遞】
/*傳入的是地址,因為地址是唯一的,所以指標通過地址的訪問進而可修改其內容,修改成功 */  
void Swap (int* pLeft, int* pRight)
{  
     int temp = *pLeft;  
     *pLeft = *pRight;  
     *pRight = temp;  
}  

3.4 引用作為返回值

引用作為返回值可以將一個函式當左值。

#include <iostream>

using namespace std;

double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};

double& setValues( int i )
{
  return vals[i];   // 返回第 i 個元素的引用
}

// 要呼叫上面定義函式的主函式
int main ()
{

   cout << "改變前的值" << endl;
   for ( int i = 0; i < 5; i++ )
   {
       cout << "vals[" << i << "] = ";
       cout << vals[i] << endl;
   }

   setValues(1) = 20.23; // 改變第 2 個元素
   setValues(3) = 70.8;  // 改變第 4 個元素

   cout << "改變後的值" << endl;
   for ( int i = 0; i < 5; i++ )
   {
       cout << "vals[" << i << "] = ";
       cout << vals[i] << endl;
   }
   return 0;
}

執行結果如下:

改變前的值
vals[0] = 10.1
vals[1] = 12.6
vals[2] = 33.1
vals[3] = 24.1
vals[4] = 50
改變後的值
vals[0] = 10.1
vals[1] = 20.23
vals[2] = 33.1
vals[3] = 70.8
vals[4] = 50

當返回一個引用時,要注意被引用的物件不能超出作用域。所以返回一個對區域性變數的引用是不合法的,但是,可以返回一個對靜態變數的引用。

int& func() {
   int q;
   //! return q; // 在編譯時發生錯誤
   static int x;
   return x;     // 安全,x 在函式作用域外依然是有效的
}

4 使用引用需要注意的地方

(1)&在這裡不是求地址運算,而是起標識作用。

(2)型別識別符號是指目標變數的型別。

(3)宣告引用時,必須同時對其進行初始化。

(4)引用宣告完畢後,相當於目標變數名有兩個名稱,即該目標原名稱和引用名,且不能再把該引用名作為其他變數名的別名。

(5)對引用求地址,就是對目標變數求地址。即引用名是目標變數名的一個別名。引用在定義上是說引用不佔據任何記憶體空間,但是編譯器在一般將其實現為const指標,即指向位置不可變的指標,所以引用實際上與一般指標同樣佔用記憶體。

(6)不能建立引用的陣列。因為陣列是一個由若干個元素所組成的集合,所以無法建立一個由引用組成的集合,但是可以建立陣列的引用。

(7)引用常見的使用用途:作為函式的引數、作為函式的返回值(注意作為返回值時,不能返回一個臨時變數的引用)。

5 引用和指標的異同點

5.1 相同點

兩者都是地址的概念,指標指向一塊兒記憶體,其內容為所指記憶體的地址;引用是某塊兒記憶體的別名。

5.2 不同點

1指標是一個實體,而引用僅是個別名;

2 引用使用時無需解引用(*),指標需要解引用;

3 引用只能在定義時被初始化一次,之後不可變;指標可變;

4 引用不能為空,指標可以為空;

5 “sizeof 引用”得到的是所指向的變數(物件)的大小,而“sizeof 指標”得到的是指標本身(所指向的變數或物件的地址)的大小;

6 指標和引用的自增(++)運算意義不一樣;

7 從記憶體分配上看:程式為指標變數分配記憶體區域,而引用不需要分配記憶體區域。

感謝:http://www.runoob.com/cplusplus/returning-values-by-reference.html
https://blog.csdn.net/xiao__tian__/article/details/51814617