[003]Reference in C++—C++引用基礎知識篇

來源:互聯網
上載者:User

最近在搞C++的引用,閑來無事,順便寫寫引用的基礎知識

引言:什麼是引用

  引用就是某一變數(目標)的一個別名,對引用的操作與對變數直接操作完全一樣。

引用的格式:

  資料類型 &引用變數名 = 目標變數名;

第一章 引用的一些基本文法

(1)&在此不是求地址運算,而是起標識作用。
(2)類型標識符是指目標變數的類型。
(3)聲明引用時,必須同時對其進行初始化。
(4)引用聲明完畢後,相當於目標變數名有兩個名稱,即該目標原名稱和引用名,且不能再把該引用名作為其他變數名的別名。
(5)聲明一個引用,不是新定義了一個變數,它只表示該引用名是目標變數名的一個別名,它本身不是一種資料類型,因此引用本身不佔儲存單元,系統也不給引用分配儲存單元。故:對引用求地址,就是對目標變數求地址。
(6)不能建立數組的引用。因為數組是一個由若干個元素所組成的集合,所以無法建立一個數組的別名。

第二章 引用的應用

1、作為函數的傳遞參數

例:

View Code

 1 #include <iostream> 2 using namespace std; 3  4 void foo(int &a, int &b) 5 { 6     int c = 0; 7     c = a + b; 8     cout << c <<endl; 9 }10 int main()11 {12     int x = 1;13     int y = 2;14     foo(x, y);15 16     system("pause");17     return 0;18 }

其效果與值傳遞是一樣的,被調函數的形參就成為原來主調函數中的實參變數或對象的一個別名來使用,所以在被調函數中對形參變數的操作就是對其相應的目標對象(在主調函數中)的操作。但需要注意的是:

①使用引用傳遞函數的參數,在記憶體中並沒有產生實參的副本,它是直接對實參操作。這樣做的好處在於:有大塊資料作為參數傳遞的時候,可以避免將整塊資料全部壓棧,可以提高程式的效率;

②要達到這種效果,使用指標傳遞也是一樣的,但是在閱讀性上,還是不如引用的,因為指標這個東東,出錯的機率很高>_<!

比如,這個就很不好看

View Code

 1 #include <iostream> 2 using namespace std; 3  4 void foo(int *a, int *b) 5 { 6     int c = 0; 7     c = *a + *b; 8     cout << c <<endl; 9 }10 int main()11 {12     int x = 1;13     int y = 2;14     foo(&x, &y);15 16     system("pause");17     return 0;18 }

2、常量引用

  事先需要說明一點:引用是不能直接來常量引用的,比如:int &a = 1;就是一個錯誤的語句。

  但是我們可以通過const來實現常量引用,上面的語句,我們可以改為:const int &a = 1;

  需要注意的是:這種方式的聲明,不能通過引用對引用變數進行修改,但是可以對目標變數名進行修正來達到目的:

View Code

#include <iostream>using namespace std;void foo(int *a, int *b){    int c = 0;    c = *a + *b;    cout << c <<endl;}int main(){    int x = 1;    int y = 2;    foo(&x, &y);    int z = 2;    const int &a =z;    //a = 5;  wrong!    z = 4;    cout << a << '\n' <<endl;    system("pause");    return 0;}

輸出結果為:

34

3、引用作為傳回值

  函式宣告格式:類型標識符 &函數名(形參列表及類型說明);

  這種使用方法的好處在於,在記憶體中不產生被傳回值的副本(即臨時變數),例如:

View Code

  使用引用作為傳回值時,還需要注意以下幾點:

①不能返回局部變數的引用。因為局部變數會在函數返回後被銷毀,因此被返回的引用就成為了"無所指"的引用,程式會進入未知狀態。

②不能返回函數內部new分配的記憶體的引用。雖然不存在局部變數的被動銷毀問題,可對於這種情況(返回函數內部new分配記憶體的引用),又面臨其它尷尬局面。例如,被函數返回的引用只是作為一個臨時變數出現,而沒有被賦予一個實際的變數,那麼這個引用所指向的空間(由new分配)就無法釋放,造成memory leak。

③可以返回類成員的引用,但最好是const。

4、引用和多態

  產生這個問題的根本來源就在於:一個基類的引用可以指向它的衍生類別執行個體。這就很容易產生一個問題:引用也會產生多態效果。

  例:

View Code

 1 #include <iostream> 2 using namespace std; 3  4 class A { 5 public: 6     A(); 7     virtual void foo() { 8         cout << "a" << endl; 9     };10 };11 12 A::A() {13 }14 15 class B: public A {16 public:17     void foo1() {18         cout << "b" << endl;19     };20 };21 22 int main()23 {24     B b;25     A &a = b;26     a.foo(); // 訪問衍生類別對象中從基類繼承下來的成員27     // a.foo1(); // wrong!28     b.foo();29     b.foo1();30     system("pause");31     return 0;32 }

第三章 引用和指標

不同點:

  ①初始化:引用必須在建立的時候就初始化,但是指標可以在任何時候被初始化

  ②引用不可為空,但是指標可以為NULL

  ③引用的對象被初始化後就無法更改,但是指標指向的對象是可以更改的

  ④記憶體:引用與被引用對象共用記憶體空間,系統不會為引用變數分配記憶體空間,但系統會為指標分配記憶體空間

  ⑤在作為形參傳遞的時候,引用不拷貝副本,指標拷貝副本

  ⑥引用訪問的對象是直接存取,而指標是間接訪問

 關係:

  引用的實現,在內部來看,其實就是用指標來實現的,可以來看一個指標和指標的引用的例子:

View Code

 1 #include <iostream> 2 using namespace std; 3  4 void foo(int *&x) { 5     *x = 100; 6 } 7  8 int main() { 9     int *x;10     x = (int *)malloc(sizeof(int));11     *x=300;12     foo(x);13     //foo(*x);// wrong cannot convert parameter 1 from 'int ' to 'int *& '14     //foo(&x);//cannot convert parameter 1 from 'int **' to 'int *& '15     cout << "*x = " << *x <<endl;16 17     system("pause");18     return 0;19 }

從上面的例子我們可以看到,其實指標的引用本質上就是雙指標。foo(*&x);這個函數也是可以編譯通過得到結果的。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.