C++詳細分析講解引用的概念與使用
1.引用的概念
引用不是新定義一個變量,而是給已存在變量取瞭一個別名,編譯器不會為引用變量開辟內存空間,它和它引用的變量共用同一塊內存空間。
2.引用的格式
類型 & 引用變量名 ( 對象名 ) = 引用實體;
舉例如下:
註意:引用類型必須和引用實體是同種類型的
3.引用的特性
(1). 引用在 定義時必須初始化
例如:int& d; 這樣就是沒有初始化是錯的
(2). 一個變量可以有多個引用
int a = 10;
int& b = a;
int& c = b;
int* p = &b; //p是指針
(3). 引用一旦引用一個實體,再不能引用其他實體
4.取別名原則
對原引用變量,權限隻能縮小,即 可讀可寫(普通類型) 可以改成 隻讀(const);不能放大:,即 隻讀 不能改成 可讀可寫的
例子1:權限的放大,不能把const給非const
例子2:權限的縮小 非const 既可以給非const,也可以給const:
例子3:權限縮小和放大規則:適用於引用和指針間
例子4: 權限不適用於普通賦值:
難點:隱式類型轉換的引用
整形e能否做雙精度浮點型d的別名呢?
直接賦值是不行的,需要加上const才正確。即:const int& e = d;
正確
解釋:隱式類型轉換的普通賦值的情況,上面的例子:int f=d;從語法上看把8字節的d不能直接給4字節的f,因為浮點數和整形的存儲形式就不一樣,沒辦法直接截取,所以d需要先把整數部分給一個4字節的臨時變量,再把臨時變量給f
再看引用:int& e=d;
臨時變量具有常性,所以這裡把臨時變量給引用e的時候,相當於是把自帶const的臨時變量賦值給非const的e,把隻讀的給可讀可寫的是放大瞭權限,所以錯誤;必須改成const int& e=d;
才正確!
5.引用的使用場景
做參數
(1)傳參:實參給形參傳值和傳地址都需要傳一份值/地址的拷貝,引用傳參可以減少拷貝,提高效率
void Swap(int& x, int& y) { int tmp = x; x = y; y = tmp; } void Swap(double& x, double& y) { double tmp = x; x = y; y = tmp; } int main() { int a = 0, b = 1; swap(a, b); double c = 1.1, d = 2.2; swap(c, d); return 0; }
(2)作輸出型參數:
leetcode上的題往往有輸出型參數,在c++中就可以用引用代替更加方便
做返回值
int&Count()的講解
傳值返回:會有一個拷貝
傳引用返回:沒有這個拷貝瞭,函數返回的直接就是返回變量的別名
int& Count() { int n = 0; n++; return n; } int main() { int ret = Count(); return 0; }
首先我們來看普通的傳值返回:普通的傳值返回需要把返回值n給一個函數類型int的臨時變量(函數類型就是返回值類型),再把臨時變量給ret。
為什麼設計一個臨時變量,直接把n給ret不行嗎?
答:不行,因為當函數Count裡執行完各種代碼後,返回n,等出瞭Count函數的作用域後n就會銷毀,所以不能直接把n給ret,需要一個臨時變量。
如何證明返回時存在臨時變量呢?:如果你用int& ret 接收,寫成int& ret = Count();
發現無法運行,因為臨時變量有常性,所以需要寫成const int& ret = Count();
才能通過。
此時再看傳引用返回:
當用引用接收引用返回時:這裡ret和n的地址一樣,也就意味著ret其實就是n的別名。但是因為n出作用域不會立即被覆蓋,所以第一次通過ret可以打印是1,當打印第二次時,因為前面已經調用過一次打印函數,已 "銷毀" 的Count函數棧幀在此時被打印函數覆蓋,再打印ret就會是隨機數瞭!
即:如果函數返回時,出瞭函數作用域,如果返回對象還未還給系統,則可以使用引用返回,如果已 經還給系統瞭,則必須使用傳值返回。
用static修飾n後:用static靜態變量使n隻初始化一次且改變其生命周期,把n放進瞭靜態區,這樣n就一直存在,就可以通過ret找到n瞭,再怎麼打印ret都是1.
傳值傳引用效率比較
以值作為參數或者返回值類型,在傳參和返回期間,函數不會直接傳遞實參或者將變量本身直接返回,而是傳遞實參或者返回變量的一份臨時的拷貝,因此用值作為參數或者返回值類型,效率是非常低下的,尤其是 當參數或者返回值類型非常大時,效率就更低。 總結:傳值和指針在作為傳參以及返回值類型上效率相差很大 。
6.引用和指針的不同點
1. 引用 在定義時 必須初始化 ,指針沒有要求
2. 引用 在初始化時引用一個實體後,就 不能再引用其他實體 ,而指針可以在任何時候指向任何一個同類型 實體
3. 沒有 NULL 引用 ,但有 NULL 指針
4. 在 sizeof 中含義不同 : 引用 結果為 引用類型的大小 ,但 指針 始終是 地址空間所占字節個數 (32 位平臺下占 4 個字節 )
5. 引用自加即引用的實體增加 1 ,指針自加即指針向後偏移一個類型的大小
6. 有多級指針,但是沒有多級引用
7. 訪問實體方式不同, 指針需要顯式解引用,引用編譯器自己處理
8. 引用比指針使用起來相對更安全
引用和指針在語法上是不一樣的,但是實際上從反匯編的代碼上我們能看到引用和指針的底層實現是一樣的!
這就好比保時捷的卡宴和大眾的途銳汽車,他們的三大件底盤,發動機,變速箱都是一樣的,但是他們的品牌不一樣,價格不同
到此這篇關於C++詳細分析講解引用的概念與使用的文章就介紹到這瞭,更多相關C++引用內容請搜索LevelAH以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持LevelAH!