引用:&(reference)與間接引用:*(dereference)
1. 符號&(reference),表示".....的地址"("address of"),因此稱為地址操作符(adress operator),又稱引用操作符(reference operator)。例如:
|
將變數myvar的地址賦給變數foo,因為當在變數名稱myvar 前面加ampersand (&) 符號,foo指的將不再是該變數的內容,而是它在記憶體中的地址。在程式執行之前,變數的記憶體地址是不可知的,但為了便於理解,我們假設myvar的記憶體地址是1776。然後我們看下列程式碼:
myvar = 25; foo = &myvar; bar = myvar; |
各自變數的儲存值如下圖所示:
儲存其它變數地址的變數(如上面例子中的foo ),我們稱之為指標(pointer)。在C++ 中,指標pointers 有其特定的優點,因此經常被使用。在後面我們將會看到這種變數如何被宣告。
2. 符號*(dereference),表示".....所指向的值"("value pointed to by"),看下面的宣告:
|
可以讀作:baz等於foo所指向的值。baz的值變為25,因為foo儲存的是記憶體地址1776,而*foo
指的是
記憶體地址1776指向的值,即25。
注意加或不加星號*的不同(下面程式碼中註釋顯示瞭如何讀這兩個不同的表示式):
beth = ted;// beth 等於 ted ( 1776 ) |
beth = *ted;// beth 等於 ted 所指向的數值 ( 25 ) |
3. 引用在函式中的使用
#include <iostream> using namespace std; int addition (int a, int b) { int r; r=a+b; return r; } int main () { int x=5, y=3, z; z = addition (x,y); cout << "The result is " << z;//The result is 8
}
上面的函式 addition 有兩個引數int a 和 int b,這兩個引數都是通過值(by value)傳遞的。它的意思是,當呼叫函式 addition(x, y)的時候,x 和 y 的值(5 和 3)會被 copy 一份,然後分別賦值給 a 和 b。在函式內部修改 a 和 b 的值,並不會對外部的 x 和 y 造成影響。
但有時候,需要在函式內部修改外部的變數,怎麼辦呢?為了實現這個需求,可以通過引用(by reference)傳參。看下面的例子
// passing parameters by reference #include <iostream> using namespace std; void duplicate (int& a, int& b, int& c) { a*=2; b*=2; c*=2; } int main () { int x=1, y=3, z=7; duplicate (x, y, z); cout << "x=" << x << ", y=" << y << ", z=" << z; //x=2, y=6, z=14 return 0; }
通過在引數型別後面新增符號 &,函式 duplicate 的三個引數都宣告成了引用。當變數 x ,y,z 以引用的方式傳入函式 duplicate 時,實際傳入的不再是變數的值的拷貝,而是變數自己。由此,在函式內部,修改 a, b, c 的值,也就是修改了外部 x ,y,z 的值。
4. 效能問題和常數引用
對於引數是通過值(by value)傳遞的函式,引數的值會被 copy 一份傳入函式。對於基本型別比如 int,這樣的開銷是很小的。但對於大的複合型別,不如 string,這樣的開銷還是很大的。比如:
string concatenate (string a, string b) { return a+b; }
如果有兩個很長的字元作為 concatenate 的引數,那麼意味著,僅僅是在呼叫這個函式的時候,就會有大量的資料被拷貝。
但是,如果我們使用引用,這樣的問題就可以被避免:
string concatenate (string& a, string& b) { return a+b; }
- 注意這種通引用 by reference 傳遞引數的方式只是在C++中適用。在C 語言中,我們必須用指標(pointers)來做相同的操作。
綜上可知,使用引用傳遞引數有兩個優勢:
1. 不需要再 copy 值,提升效能。
2. 修改了引數的值也就修改了外部變數的值。
如果只想利用第1點,避免第2點,怎麼辦?方法是把引數宣告為常量(constant):
string concatenate (const string& a, const string& b) { return a+b; }
這樣,使用常量引用,既達到了像值傳遞那樣使用引數,又可以像引用傳遞那樣提升效能。