細說引用和指針

[文獻參考]

《C++ Primer (第4版)》Stanley B.Lippman 著 ——人民郵電出版社

《c++語言程序設計(第4版)》 鄭莉 董源 何江舟 著——清華大學出版社

<C++程序設計教程(第二版)>》錢能著 ——清華大學出版社


   引用和指針有許多相似之處,例如它們都可以避免值複製的發生,從而減少函數調用時數據傳遞的開銷。那麼它們在深層中又有什麼聯繫嗎?

    在程序運行中,變量只能依靠地址來區別。因此,只有通過存儲被引用變量的地址,在運行時才能準確定位被引用的變量。

    引用本身所佔用的岑村空間中,存儲的就是被引用變量的地址,這和指針變量所存儲的內容具有相同的性質。

    指針式一種底層的機制,引用則是一種較高層的機制,在語言概念上引用是另一變量的“別名”,把地址這一概念隱藏起來了(所以對引用取地址獲得的時被引用變量的地址,而非引用本身的地址)。它們的差異主要在語言形式上,實際上都是靠存儲地址來實現的。

    引用與指針的顯著區別是,普通指針可以被多次賦值,即是可以多次更改它所指向的對象,二引用只能在初始化時指定被引用的對象,去後不能更改,所以,引用的功能具有指針常量的性質。

下圖爲它們的對應關係:

操作 T類型的指針常量 對T類型的引用
定義並用v初始化(v是T類型變量) T * const p = &v; T &r = v;
取v的值 *p r
訪問成員m p->m r.m
讀取v的地址 p &r


可以肯定地說,能用引用實現的功能,用指針都可以實現。

既然這樣,爲什麼還要引入引用這一概念呢?

指針是一種兼顧C語言特性的底層機制,正因爲其底層,使用起來很靈活,功能強大。然而,正因爲太過靈活,反而變得不好用。考慮一下情況:

①如果希望使用指針作爲函數參數達到數據雙向傳遞或減少傳遞開銷的目的,在主調函數中需要用“&”傳遞參數,在被調用函數中需要用“*”訪問數據,程序難免顯得太過繁瑣。

②編譯器不會檢查指針越界,有些情況下不需要指針的算術運算,這時如果對指針進行算術運算,會造成不必要的麻煩。

爲了能夠滿足更加方便、安全的處理數據雙向傳遞,減少參數傳遞開銷這樣的簡單需求,引用這一概念被引入了C++中。

下面通過swap函數可比較指針和引用書寫和使用上的繁簡:

//使用指針常量 
void swap(int * const pa, int * const pb)
{
	int temp = *pa;
	*pa = *pb;
	*pb = *pa;
}

int main()
{
	int a, b;
	...
	swap(&a, &b);
	...
	return 0;
}


//使用引用 
void swap(int &ra, int &b)
{
	int temp = ra;
	ra = rb;
	rb = ra;
}

int main()
{
	int a, b;
	...
	swap(a, b);
	...
	return 0;
}


對於數據參數傳遞、減少大對象的參數傳遞開銷這兩個用途來說,引用可以很好的代替指針,使用引用比使用指針更加簡潔、安全。


但有些時候,引用還不能完全替代指針,具體如下:

(1)如果一個指針所指向的對象,需要用分支結構加以確定,或者在中途需要改變它所指向的對象,那麼在他初始化之後需要爲它賦值,此時引用不能勝任。

(2)有時指針的值可能是一個空指針,空指針在一些情況下表達特定的含義,如ctime頭文件中的time函數。

(3)使用指針函數,而沒有函數引用。

(4)用new動態創建的對象或數組,需要用指針來存儲它的地址。

(5)以數組形式傳遞大批量數據時,需要用指針類型接收參數。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章