爲什麼要在c++中引入“引用?
按照c++之父斯特勞斯特魯普的說法是:(以下內容摘抄自斯特勞斯特魯普的個人網站)
C++ 的指針繼承於 C,若要移除指針,勢必造成嚴重的兼容性問題。引用有幾方面的用處,但我在 C++ 中引入它的主要目的是爲了支持運算符重載。例如:
void f1(const complex* x, const complex* y) // 沒有引用
{
complex z = *x+*y; // 難看
// ...
}
void f2(const complex& x, const complex& y) // 使用引用
{
complex z = x+y; // 看起來不錯
// ...
}
我們在學習c++過程中,會覺得引用是一個非常簡單好用的東西,但仔細體會會發現它的一些特性不太好捉摸,下面總結下:
引用的本質是什麼?
我覺得要說清楚這個話題需要對引用有2個方面的理解,一個是“單純的c++規範”層面的理解,另一個是各個編譯器廠家如何“實現引用”的層面來理解。
1. “單純的c++規範”層面:引用是一個具名變量的別名,這個所有c++書籍上都會介紹的,但這句背後的含義是什麼呢?答案是”引用不是對象”!!!對象是什麼呢?你可能會說:對象就是“new出來的東西”。但嚴格來說應當是:
對象是帶有一些性質的儲存區域,這些性質包括:大小(sizeof),內存對齊,生命週期,連接性,類型,名字(new 出來的對象是不具名對象,沒有名字)。
在c++中有哪些地方能體現出來“引用不是對象”呢?看代碼:
int* arr1[10]; //指針數組,每個位置上放置一個指向int類型的指針
int& arr2[10]; //error,沒有這種寫法,沒有存放引用的數組,因爲引用不是對象
int& *p = NULL; //error,沒用指向指針的引用
int && p; //error,沒有指向應用的應用,這裏其實一個右值引用,p需要用一個臨時量初始化
這一層面的理解關鍵是知道:引用不是對象。
2. 編譯器如何“實現引用”:編譯器通過“自解引用的常量指針”來實現引用的效果。看代碼:
int num = 90;
int & r = num;
//等價於
int * const r = # //這也是引用爲什麼要初始化的原因
cout<<r<<endl; //輸出num
//等價於
cout<<*r<<endl;
總結:引用需要理解到這兩個層面才能理解一些問題。
1. c++中爲什麼沒有“引用數組”,“指向引用的指針”,“指向引用的引用”,原因是“引用不是對象”。
2.不是說“引用不是對象嗎?” 爲什麼函數傳參時,以及函數的返回值可以引用?(函數也不是對象,因此函數傳參不能傳遞,函數的返回值也不能是函數,實際上傳遞的都是指向函數的指針)。這時應當把引用理解成“引用是一個const指針”。