C++引用的概念以及基本使用


引言

引用是C++的新增內容,在實際開發中會經常使用;C++用的引用就如同C語言的指針一樣重要,但它比指針更加方便和易用。

我們知道,參數的傳遞本質上是一次賦值的過程,即將一塊內存上的數據復制到另一塊內存上。
對於像 char、bool、int、float 等基本類型的數據,它們占用的內存往往只有幾個字節,對它們進行內存拷貝非常快速。而數組、結構體、對象是一系列數據的集合,數據的數量沒有限制,可能很少,也可能成千上萬,對它們進行頻繁的內存拷貝可能會消耗很多時間,拖慢程序的執行效率。
C/C++ 禁止在函數調用時直接傳遞數組的內容,而是強制傳遞數組指針。而對於結構體和對象沒有這種限制,調用函數時既可以傳遞指針,也可以直接傳遞內容;為了提高效率,建議傳遞指針。
但是在 C++ 中,我們有了一種比指針更加便捷的傳遞聚合類型數據的方式,那就是引用(Reference)


 一,引用的概念

引用(Reference)是 C++ 相對於C語言的又一個擴充。引用可以看做是數據的一個別名,通過這個別名和原來的名字都能夠找到這份數據。引用類似於 Windows 中的快捷方式,一個可執行程序可以有多個快捷方式,通過這些快捷方式和可執行程序本身都能夠運行程序;引用還類似於人的綽號(筆名),使用綽號(筆名)和本名都能表示一個人。
引用的定義方式類似於指針,只是&取代了*,語法格式為:

type &name = data;

type 是被引用的數據的類型,name 是引用的名稱,data 是被引用的數據。引用必須在定義的同時初始化,並且以后也要從一而終,不能再引用其它數據,這有點類似於常量(const 變量)。

下面是一個演示引用的實例:

int main()
{
    int a = 11;
    int& b = a;//&引用定義
    cout << "a的值:" << a << "\n" << "b的值:" << b << endl;
    cout << "a的地址:" << &a << "\n" << "b的地址:" << &b << endl;//&取地址符

}

 可以看的,變量b就是變量a的引用,二者指向同一個地址,也可以說變量b是變量a的另一個名字。

需要注意的是:

  • 引用在定義時需要添加&,在使用時不能添加&,使用時添加&表示取地址。
  • 對變量b進行修改時,變量a的值也會改變。

二,引用作為函數參數(將形參和實參綁定)

引用作為函數參數時有兩種原因:

  1. 在函數內部會對此參數進行修改
  2. 提高函數調用和運行效率

關於第一點:

都知道C++里提到函數就會提到形參和實參。函數的參數實質就是形參,不過這個形參的作用域只是在函數體內部,也就是說實參和形參是兩個不同的東西,要想形參代替實參,肯定有一個值的傳遞。函數調用時,值的傳遞機制是通過“形參=實參”來對形參賦值達到傳值目的,產生了一個實參的副本。即使函數內部有對參數的修改,也只是針對形參,也就是那個副本,實參不會有任何更改。函數一旦結束,形參生命也宣告終結,做出的修改一樣沒對任何變量產生影響。
例如:(對兩個變量進行交換處理。此處函數的形參為p1, p2,沒有引用)

void swap(int p1,int p2)
{
    int temp;
    temp = p1;
    p1 = p2;
    p2 = temp;
}
int main()
{
    int a, b;
    cin >> a >> b; //輸入a,b兩變量的值
    swap(a, b);//直接以變量a和b作為實參調用swap函數
    cout << a << b << endl;//輸出結果
}

你會發現輸出的a和b還是你輸入的值,沒有交換。

修改為:(對兩個變量進行交換處理。此處函數的形參為p1, p2都是引用)

void swap(int &p1,int &p2)
{
    int temp;
    temp = p1;
    p1 = p2;
    p2 = temp;
}
int main()
{
    int a, b;
    cin >> a >> b; //輸入a,b兩變量的值
    swap(a, b);//直接以變量a和b作為實參調用swap函數
    cout << a << b << endl;//輸出結果
}

再次執行,就會發現值交換了。

原理就在於采用&p1和&p2時,p1和p2是實參的別名而已,像一個指針指向實參。改變p1和p2就是改變實參的值。

關於第二點:

可以結合第一點分析,p1和p2是實參的引用,不用經過值的傳遞機制,已經有了實參值的信息。所以沒有了傳值和生成副本的時間和空間消耗。當程序對效率要求比較高時,這是非常必要的.


 拓展:

前面演示了直接轉遞參數,和引用傳參。我們還可以用傳遞指針來實現。

void swap(int *p1,int *p2)
{
    int temp;
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
int main()
{
    int a, b;
    cin >> a >> b; //輸入a,b兩變量的值
    swap(&a, &b);//直接以地址作為實參調用swap函數
    cout << a << b << endl;//輸出結果
}

三,引用作為函數返回值

引用除了可以作為函數形參,還可以作為函數返回值。

說明:

(1)以引用返回函數值,定義函數時需要在函數名前加&

(2)用引用返回一個函數值的最大好處是,在內存中不產生被返回值的副本。

當函數返回一個引用時,則返回一個指向返回值的隱式指針。這樣,函數就可以放在賦值語句的左邊。

int function1(int& aa)//以返回值的方法返回函數值
{
    return aa;
}
int& function2(int& aa)//以引用方式返回函數值
{
    return aa;
}
int main()
{
    int a = 10;
    //第一種情況,系統生成要返回值的副本(即臨時變量)
   int b = function1(a);//function1()的返回值先儲存在一個臨時變量中,
                     //然后再把臨時變量賦值給b
   //第二種情況,報錯
   // function1(a) = 20;// function1()的返回值為臨時變量,不能賦值(即不能為左值)
   //第三種情況,系統不會生成返回值的副本
    function2(a) = 20;//OK  此時a的值變成了20
}

說明:若函數的返回值為引用(&),則編譯器就不為返回值創建臨時變量了。直接返回那個變量的引用。所以千萬不要返回臨時變量的引用,如下:

int & function()
{
    int b = 10;
    return b;//不OK 等函數返回后,b就消失了,引用了一個消失的東西
             //程序會懵逼的。指針也一樣。
}
int main()
{
    int a;
    a = function();//function()返回的東西已經消失了,引用也就不存在了
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM