引入
C語言中函數有兩種傳參的方式: 傳值和傳址。以傳值方式, 在函數調用過程中會生成一份臨時變量用形參代替, 最終把實參的值傳遞給新分配的臨時變量即形參。 它的優點是避免了函數調用的副作用, 確無法改變形參的值。 如果要改變實參的值, 只 能通過指針傳遞。
1 void swap (int left, int right) 2 { 3 int temp = left; 4 left = right; 5 right = temp; 6 } 7 void swap (int *_pleft , int * _pRight) 8 { 9 assert (NULL ! = _pleft && NULL ! = _pRight) ; 10 int iTemp = * _pleft; 11 *_pleft = * _pRight; 12 *_pRight = iTemp;
13 }
指針可以解決問題, 但不是很形象友好, 不安全, 因 此C++中 引 入了 一種新的符合類型--引用 。
引用概念
引用(reference)不是新定義一個變量, 而是給已存在的對象取了 一個別名 ,引用類型,引用另外一種類型。 編譯器不會為引用對象新開辟內存空間, 它和它引用的對象共用同一塊內存空間 。
1 int num = 110; 2 int &number = num; //number指向num(是num的另外一個名字)
一般在初始化變量時,初始值會被拷貝到新建的對象中。然而定義引用時程序把引用和他的初始值綁定在一起,而不是將初始值拷貝給引用。一旦初始化完成引用家將和他的初始對象一直綁定在一塊。因為無法將引用重新綁定到另外一個對象上,因此引用必須初始化。
引用即別名
引用並非對象,相反的,它只是為一個已經存在的對象所起的另外一個名字。定義一個引用之后,對其進行的所有操作都是在與之綁定的對象上進行的:
1 number = 120; //把120賦給number指向的對象,此處即是賦給了num 2 int tmp = number; //與tmp = num執行結果一樣
為引用賦值,實際上是把值賦給了與引用綁定的對象。獲取引用的值,實際上是獲取了與引用綁定的對象的值。同理,以引用作為初始值,實際上是以引用綁定的對象作為初始值。
引用的定義
允許在一條語句中定義多個引用,其中每個引用標識符都必須以&開頭;
因為無法將引用重新綁定到另外一個對象上,因此引用必須初始化。
因為引用本身不是一一個對象,所以不能定義引用的引用。
一個變量可以有多個引用,而一個引用只能給一個變量對象 。
引用的類型要和與之綁定的對象嚴格匹配(不嚴謹)。
引用只能綁定在對象上而不能和字面值或某個表達式計算的記過綁定在一起。
1 int i1 = 10, i2 = 20 ; //i1和i2都是int型 2 int &r1 = i1, &r2 = i2; //r1和r2都是引用 3 int &r3 ; //報錯:引用必須初始化 4 int &r4 = i1, &r5 = i2; //r1, r4同為i1的引用,r2, r5同為i2的引用 5 int &r4 = i2, &r5 = i1; //報錯:r4不能同時分別為i1和i2的引用 6 int &r6 = 10; //報錯:引用類型的初始值必須是一個對象 7 double i3 = 3.14; 8 int &r7 = i3; //報錯:此處引用類型的初始值必須是int型對象
引用與指針
相同點:
底層的實現方式相同, 都是按照指針的方式來實現的:
不同點:
有空指針,沒有空引用;
引用定義時必須初始化, 指針可以不用, 正常情況下需初始化為NULL;
引用一旦定義就不能再改變, 指針可以;
sizeof求取的值不一樣;
自 ++含義不同;
可以有多級指針, 但是沒有多級引 用;
指針和引用的地址不同;
int**/int&&意義不同;
總結:
1、 引 用在定義時必須初始化, 指針沒有要求。
2、 一旦一個引 用被初始化為指向一個對象, 就不能再指向其他對象, 而指針可以在任何時候指向任何一個同類型對象。
3、 沒有NULL引 用, 但有NULL指針。
4、 在sizeof中含義不同: 引 用結果為引 用類型的大小,但指針始終是地址空間所占字節個數。
5、 引 用自 加改變變量的內 容, 指針自 加改變了 指針指向。
6、 有多級指針, 但是沒有多級引用。