網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
引用
1.引用概念
引用不是新定義一個(gè)變量,而是給已存在變量取了一個(gè)別名,編譯器不會(huì)為引用變量開(kāi)辟內(nèi)存空間,它和它引用的變量共用同一塊內(nèi)存空間。
比如:李逵,在家稱(chēng)為"鐵牛",江湖上人稱(chēng)"黑旋風(fēng)
2.格式
類(lèi)型& 引用變量名(對(duì)象名) = 引用實(shí)體;
例:
void TestRef() { int a = 10; int& ra = a;//<====定義引用類(lèi)型 printf("%p\n", &a); printf("%p\n", &ra); }
注意:引用類(lèi)型必須和引用實(shí)體是同種類(lèi)型的
3.引用特性
引用在定義時(shí)必須初始化一個(gè)變量可以有多個(gè)引用引用一旦引用一個(gè)實(shí)體,再不能引用其他實(shí)體
例:
引用實(shí)例:
4.常引用
1.const引用
eg1:
const引用在傳參引用時(shí)的意義:
1.可以保護(hù)形參返回不會(huì)改變實(shí)參的值(函數(shù)傳參如果想減少拷貝而用了引用傳參,如果函數(shù)中不改變這個(gè)參數(shù),最好用const引用傳參)
2.即可接受變量,也可接受常量。
eg2:
5.使用場(chǎng)景
1、引用作為參數(shù)
引用的一個(gè)重要作用就是作為函數(shù)的參數(shù)。以前的C語(yǔ)言中函數(shù)參數(shù)傳遞是值傳遞,如果有大塊數(shù)據(jù)作為參數(shù)傳遞的時(shí)候,采用的方案往往是指針,因?yàn)?這樣可以避免將整塊數(shù)據(jù)全部壓棧,可以提高程序的效率。但是現(xiàn)在(C++中)又增加了一種同樣有效率的選擇(在某些特殊情況下又是必須的選擇),就是引 用。
[例]:
void Swap(int& left, int& right) { int temp = left; left = right; right = temp; } int main() { int a,b; cin>>a>>b; //輸入a,b兩變量的值 swap(a,b); //直接以變量a和b作為實(shí)參調(diào)用swap函數(shù) cout<<a<< ' ' <<b; //輸出結(jié)果 }
由【例】可看出:
(1)傳遞引用給函數(shù)與傳遞指針的效果是一樣的。這時(shí),被調(diào)函數(shù)的形參就成為原來(lái)主調(diào)函數(shù)中的實(shí)參變量或?qū)ο蟮囊粋€(gè)別名來(lái)使用,所以在被調(diào)函數(shù)中對(duì)形參變量的操作就是對(duì)其相應(yīng)的目標(biāo)對(duì)象(在主調(diào)函數(shù)中)的操作。
(2)使用引用傳遞函數(shù)的參數(shù),在內(nèi)存中并沒(méi)有產(chǎn)生實(shí)參的副本,它是直接對(duì)實(shí)參操作;而使用一般變量傳遞函數(shù)的參數(shù),當(dāng)發(fā)生函數(shù)調(diào)用時(shí),需要給 形參分配存儲(chǔ)單元,形參變量是實(shí)參變量的副本;如果傳遞的是對(duì)象,還將調(diào)用拷貝構(gòu)造函數(shù)。因此,當(dāng)參數(shù)傳遞的數(shù)據(jù)較大時(shí),用引用比用一般變量傳遞參數(shù)的效 率和所占空間都好。
(3)使用指針作為函數(shù)的參數(shù)雖然也能達(dá)到與使用引用的效果,但是,在被調(diào)函數(shù)中同樣要給形參分配存儲(chǔ)單元,且需要重復(fù)使用"*指針變量名"的 形式進(jìn)行運(yùn)算,這很容易產(chǎn)生錯(cuò)誤且程序的閱讀性較差;另一方面,在主調(diào)函數(shù)的調(diào)用點(diǎn)處,必須用變量的地址作為實(shí)參。而引用更容易使用,更清晰。
2. 引用作為做返回值
下面代碼輸出什么結(jié)果?為什么?
int& Add(int a, int b) { int c = a + b; return c; } int main() { int ret = Add(1, 2); Add(3, 4); cout << "Add(1, 2) is :"<< ret <<endl; return 0; }
對(duì)于以上代碼,是將c
的別名傳給了ret
,結(jié)果確不確定,取決于平臺(tái)銷(xiāo)毀棧幀時(shí),是否清理?xiàng)臻g(由運(yùn)行結(jié)果知;vs下不清理)
那么我們進(jìn)一步改動(dòng)實(shí)驗(yàn)證明引用返回的危害:
int& Add(int a, int b) { int c = a + b; return c; } int main() { int &ret = Add(1, 2); Add(3, 4); cout << "Add(1, 2) is :" << ret << endl; return 0; }
此時(shí)相當(dāng)與ret
是c
的別名,再次運(yùn)行:
結(jié)果出錯(cuò)。
舉個(gè)恰當(dāng)?shù)睦樱?/strong>
因此注意:如果函數(shù)返回時(shí),出了函數(shù)作用域,如果返回對(duì)象還未還給系統(tǒng),則可以使用引用返回,如果已經(jīng)還給系統(tǒng)了,則必須使用傳值返回。
傳值、傳引用效率比較:
以值作為參數(shù)或者返回值類(lèi)型,在傳參和返回期間,函數(shù)不會(huì)直接傳遞實(shí)參或者將變量本身直接返回,而是傳遞實(shí)參或者返回變量的一份臨時(shí)的拷貝,因此用值作為參數(shù)或者返回值類(lèi)型,效率是非常低下的,尤其是當(dāng)參數(shù)或者返回值類(lèi)型非常大時(shí),效率就更低。
例:
#include <time.h> struct A{ int a[10000]; }; void TestFunc1(A a){} void TestFunc2(A& a){} void TestRefAndValue() { A a; // 以值作為函數(shù)參數(shù) size_t begin1 = clock(); for (size_t i = 0; i < 10000; ++i) TestFunc1(a); size_t end1 = clock(); // 以引用作為函數(shù)參數(shù) size_t begin2 = clock(); for (size_t i = 0; i < 10000; ++i) TestFunc2(a); size_t end2 = clock(); // 分別計(jì)算兩個(gè)函數(shù)運(yùn)行結(jié)束后的時(shí)間 cout << "TestFunc1(A)-time:" << end1 - begin1 << endl; cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl; }
值和引用的作為返回值類(lèi)型的性能比較:
#include <time.h> struct A{ int a[10000]; }; A a; // 值返回 A TestFunc1() { return a;} // 引用返回 A& TestFunc2(){ return a;} void TestReturnByRefOrValue() { // 以值作為函數(shù)的返回值類(lèi)型 size_t begin1 = clock(); for (size_t i = 0; i < 100000; ++i) TestFunc1(); size_t end1 = clock(); // 以引用作為函數(shù)的返回值類(lèi)型 size_t begin2 = clock(); for (size_t i = 0; i < 100000; ++i) TestFunc2(); size_t end2 = clock(); // 計(jì)算兩個(gè)函數(shù)運(yùn)算完成之后的時(shí)間 cout << "TestFunc1 time:" << end1 - begin1 << endl; cout << "TestFunc2 time:" << end2 - begin2 << endl; }
通過(guò)上述代碼的比較,發(fā)現(xiàn)傳值和指針在作為傳參以及返回值類(lèi)型上效率相差很大
6.引用和指針的區(qū)別
在語(yǔ)法概念上引用就是一個(gè)別名,沒(méi)有獨(dú)立空間,和其引用實(shí)體共用同一塊空間 在底層實(shí)現(xiàn)上實(shí)際是有空間的,因?yàn)橐檬前凑罩羔樂(lè)绞絹?lái)實(shí)現(xiàn)的:
實(shí)例:
int main() { int a = 10; int& ra = a; ra = 20; int* pa = &a; *pa = 30; return 0; }
我們來(lái)看下引用和指針的匯編代碼對(duì)比:
7.引用和指針的不同點(diǎn):
引用在定義時(shí)必須初始化,指針沒(méi)有要求
引用在初始化時(shí)引用一個(gè)實(shí)體后,就不能再引用其他實(shí)體,而指針可以在任何時(shí)候指向任何一個(gè)同類(lèi)型 實(shí)體沒(méi)有NULL引用,但有NULL指針在sizeof中含義不同:引用結(jié)果為引用類(lèi)型的大小,但指針始終是地址空間所占字節(jié)個(gè)數(shù)(32位平臺(tái)下占 4個(gè)字節(jié))引用自加即引用的實(shí)體增加1,指針自加即指針向后偏移一個(gè)類(lèi)型的大小有多級(jí)指針,但是沒(méi)有多級(jí)引用訪問(wèn)實(shí)體方式不同,指針需要顯式解引用,引用編譯器自己處理
引用比指針使用起來(lái)相對(duì)更安全
總結(jié)
原文鏈接:https://blog.csdn.net/weixin_53306029/article/details/121194500
相關(guān)推薦
- 2022-09-03 Go語(yǔ)言函數(shù)的延遲調(diào)用(Deferred?Code)詳解_Golang
- 2022-10-07 詳解Python?OpenCV圖像分割算法的實(shí)現(xiàn)_python
- 2022-11-05 C/C++讀取大文件數(shù)據(jù)方式詳細(xì)講解_C 語(yǔ)言
- 2023-07-08 keycloak更新token調(diào)用updateToken函數(shù)無(wú)效,解決辦法
- 2022-05-13 C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之堆排序詳解_C 語(yǔ)言
- 2022-08-23 Python?Pandas數(shù)據(jù)處理高頻操作詳解_python
- 2022-12-07 C++11,?14,?17對(duì)tuple元素的訪問(wèn)詳情_(kāi)C 語(yǔ)言
- 2021-11-18 詳解C++中inline關(guān)鍵字的作用_C 語(yǔ)言
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支