網站首頁 編程語言 正文
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. 引用比指針使用起來相對更安全
引用和指針在語法上是不一樣的,但是實際上從反匯編的代碼上我們能看到引用和指針的底層實現是一樣的!
這就好比保時捷的卡宴和大眾的途銳汽車,他們的三大件底盤,發動機,變速箱都是一樣的,但是他們的品牌不一樣,價格不同
原文鏈接:https://blog.csdn.net/zhang_si_hang/article/details/124689560
相關推薦
- 2022-06-20 一文搞懂Python的hasattr()、getattr()、setattr()?函數用法_pyth
- 2022-10-26 Anaconda環境變量的配置圖文詳解_python
- 2022-04-30 Python的進制轉換和ASCLL轉換你了解嗎_python
- 2022-05-11 批量導入模板數據的時候遇到的一些關于多線程的問題
- 2022-08-19 ubuntu上設置Redis開機自啟
- 2022-08-18 利用Redis實現訂單30分鐘自動取消_Redis
- 2023-01-28 詳解如何利用C#實現漢字轉拼音功能_C#教程
- 2023-06-16 C語言函數調用底層實現原理分析_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支