引用變量
引用是已定義變量的別名
創建引用
int a;
int & b = a; // b爲a的引用
- 引用(&),b 爲 a 的別名
- 在函數引用時,必須對其初始化
- 一個變量可以有多個引用,一個引用只能指向一個實體
- a 和 b 指向的是同一塊內存空間
將引用作爲參數
引用作爲函數參數,使得函數中的變量名成爲調用函數程序中的變量的別名。這種傳遞稱爲引用傳遞,按引用傳遞允許被調用函數能訪問調用函數中的變量。
void swapr(int & a,int & b); // 引用傳遞
void swapv(int a,int b); // 值傳遞
void swapp(int * a,int * b); // 指針傳遞
swap()
爲交換函數,上面三個分別參數爲引用、值、指針。經過我的一番測試發現。函數中的值傳遞並不能改變調用函數中a , b的值。引用和指針則可以。
引用時儘可能使用const
- 使用const能避免無意中修改數據的編程錯誤
- 使用const能夠處理const和非const實參,否則只能接受非const數據
- 使用const引用使函數能正確的生成並使用臨時變量
// 函數聲明
double cube(double &a)
{
a = a * a;
}
// 調用函數
cube(x+2);
當函數cube()
的引用參數應該是可以修改的,但是傳遞的值是(x+2)並不是變量,所以編譯時會出現錯誤。
但是,如果在引用前加上const
程序就能運行了,const
指定引用不能被修改,所以是否爲變量也就不重要了。但是編譯器會爲其創建一個臨時變量,保存(x+2),然後將 a 成爲臨時變量的引用。
那麼什麼情況下會創建臨時變量呢?如果引用參數是const,則編譯器會在下面兩種情況生成臨時變量:
- 實參的類型正確,但不爲左值
- 實參的類型不正確,但可以轉化爲右值
結構的引用
引用非常適合結構和類。引入引用主要是爲了用於這些類型,而非用於基本的內置類型。
引用這麼高效爲什麼內置類型不使用引用呢?
《Effective C++》條款20:寧以pass by reference to const替換pass by value。其中有這麼一句“如果你有個對象屬於內置類型(例如int),pass by value 往往比pass by reference的效率高些”。說白了就是自己的東西用的更順手一些。
使用結構變量引用參數和基本變量一用參數相同,就相當於別名,這裏就不贅述了。
返回一個引用
引用既然能作爲參數,那麼能否作爲返回值呢? 答案是肯定的。
爲什麼要返回引用呢? 毫無疑問,爲了讓程序效率更高。
// 聲明函數:返回值是struct_a 類型的引用
struct_a & run(struct_a & a,const struct_a & b)
{
...
return a;
}
// dup接收run的返回值
struct_a dup = run(a,b);
當函數run()
返回值爲類型時,dup接收的是一個結構,將把一個結構複製到一個臨時位置,再將這個拷貝複製給dup,消耗空間且效率低。
但返回值爲引用時,直接將a 複製到dup,效率更高
注意:在返回值爲引用時不能返回棧空間的值,函數中創建的臨時變量即使爲引用,但是函數結束後棧空間的內容都會被銷燬,返回將會出現錯誤。
總結
使用引用參數的原因:
- 修改調用函數中的函數對象
- 通過傳遞引用而不是整個數據對象,提高程序的運行速度
當數據對象較大的時候,第二個原因尤爲重要。這些也是使用指針參數的原因。
那麼指針參數和引用又有什麼區別呢?
引用參數實際上是基於指針的代碼的另一個接口,至此,引用展現了它的廬山真面目,其實它和指針在底層實現沒什麼兩樣,只是在使用上,有時引用會更加順手。
那麼什麼情況下,應該使用何種傳遞參數的方式呢?
- 數據對象小且不做修改,例如內置類型和小型結構,按值傳遞。
- 數據對象數組,只能使用指針傳遞。
- 結構,引用和指針都可以
- 類,使用引用。