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; }
這樣,使用常量引用,既達到了像值傳遞那樣使用參數,又可以像引用傳遞那樣提升性能。