網站首頁 編程語言 正文
一.引入
在生活中,我們可能也會給一些同學起外號,以“張磊”同學為例,我們可以叫他“張三石”,當我們叫到這個外號的時候就會自然而然的想到“張磊”同學,”張三石”就是張磊的別名,而引用也可以這樣簡單理解:在語法層面上,引用就是取別名。
二.C++中較為麻煩的運算符
C++中的 * 和 & 有多重含義,在不同的使用條件下有不同的意思:
*
int *p = &a; /1.指針 a = a * b; /2.乘法 *p = 100; /3.指向
&
int c = a&b; /1.位運算 轉換為二進制 int *p = &a; /2.取地址 int a = 100; int & ar = a; /3.引用
三.引用的定義
引用不是新定義一個變量,而是給已存在變量取了一個別名,編譯器不會為引用變量開辟內存空間,它與引用的變量共用同一塊內存空間。
格式如下:
類型 & 引用變量名(對象名) = 引用實體
注意這里的空格是可選的,即
- &符號與前后均可以有一個空格;如下:
int & ra=a;
- &符號與類型挨著,如下:
int& ra=a;
- &符號與引用名稱挨著,如下:
int &ra=a;
int main() { int a =100; \\定義變量名 int b = a;\\將a的值賦給變量 int &c = a;\\引用 將c作為a的別名 c11中成為左值引用 return 0; }
在這里就是相當于一個實體取了兩個名字分別為a和c,并且在這個空間中不開辟新的空間。
四.引用的特點
- 定義引用時必須給初始化
- 沒有空引用
- 沒有所謂的二級引用
- 一個變量可以有多個引用(就相當于一個變量有好幾個別名,這是可以的)
說明:
int main() { int a = 10; int& b = a; int& x; int& y = NULL; int&& c = a; }
總而言之:
引用本身是一個變量,但是這個變量又僅僅是另外一個變量一個別名,它不占用內存空間,它不是指針哦!僅僅是一個別名!
五.對比指針與引用
我們以交換函數為例
使用指針交換兩個整型值:
int my _swap (int*ap, int*bp) { assert(ap != NULL && bp != NULL); int tmp = *ap;*ap = *bp;*bp = *ap; } int main() { int x = 10, y = 20; my_swap{&x,&y); cout<< "x = " << x << " y = " << y << endl; return 0; }
使用引用交換兩個指針:
void my_swap (int& a,int& b) { int tmp = a;a = b; b = tmp; } int main () { int x = 10, y = 20;my_swap(x,y) ; cout << " x = " << x<< " y = " << y << endl; return 0; }
形參為指針時:第一句話一定要斷言,必須判斷空不空;并且在使用指針的時候 我們需要注意:是否為 野指針, 空指針 ,失效指針。
當我們使用引用時,不存在NULL引用,不需要判空,比指針更加安全
所以:能不使用指針就盡量不要使用指針!?
六.引用與指針的區(qū)別
1.語法層面的區(qū)別
從語法規(guī)則上講,指針變量存儲某個實例(變量或對象)的地址;
引用是某個實例的別名。
程序為指針變量分配內存區(qū)域;而不為引用分配內存區(qū)域。
int main() { int a = 10; int* ip = &a; int& b = a; \\b是a的別名 并沒有分配新的空間 }
解引用是指針使用時要在前加“*”;引用可以直接使用。
int main() { int a = 10; int* ip = &a; int& b = a; *ip = 100;//對于指針使用加“*” b = 200; //引用不需要“*” }
指針變量的值可以發(fā)生改變,存儲不同實例的地址;
引用在定義時就被初始化,之后無法改變(不能是其他實例的引用)。
int main() { int a = 10,b = 20; int* ip = &a; ip = &b ; int& c = a; c = b; //b的值給c實則是把b的值給a,將a的值改為20 }
指針變量的值可以為空(NULL,nullptr);沒有空引用。
指針變量作為形參時需要測試它的合法性(判空NULL);引用不需要判空。
對指針變量使用"sizeof"得到的是指針變量的大小; 對引用變量使用"sizeof"得到的是變量的大小。
int main() { double dx = 10; double* dp = &dx; double& a = dx; printf("sizeof(dp):%d\n", sizeof(dp)); printf("sizeof(a):%d", sizeof(a)); }
運行結果:
理論上指針的級數沒有限制;但引用只有一級。
即不存在引用的引用,但可以有指針的指針。
++引用與++指針的效果不一樣。
例如就++操作而言:
int main() ( int ar[5] = { 1,2,3,4,5 }; int* ip = ar; //數組首元素地址 int& b = ar[O]; //數組首元素的別名叫b ++ip; //由0下標的地址指向1下標的地址 ++b; //由0下標指向1下標 }
對引用的操作直接反應到所引用的實體(變量或對象)。對指針變量的操作,會使指針變量指向下一個實體(變量或對象)的地址;而不是改變所指實體(變量或對象)的內容。
int main() ( int ar[5] = { 1,2,3,4,5 }; int* ip = ar; //數組首元素地址 int& b = ar[O]; //數組首元素的別名叫b ++(*ip); //值由1>>2 (*ip)++; //所有表達式結束后 進行++ //有括號 先取ip的值與*結合 然后++為所指之物的++ int x = *ip++; //沒有括號 先將ip的值取出 與*結合 把所指之物取出(此時已與*結合完) 然后將ip取出進行++ ++后的值回寫給ip 將值存儲到x中 //通過()提高了優(yōu)先級 }
不可以對函數中的局部變量或對象以引用或指針方式返回。
當變量的生存期不受函數的影響時就可以返回地址
2.匯編層面的區(qū)別
匯編層面來講引用就是一個指針,但是引用并不是一個普通的指針是指針的語法槽,也可以看作是常性的指針 。
int main() { int a = 10; int* ip = &a; int& x = a; *ip = 100; x = 200; }
七.引用的其他使用
常引用
常引用實際上是一種萬能引用既可以引用普通變量 ,常量,也可以引用字面常量。
(1)引用普通變量
int main() { int a = 10; int & b = a; const int& c = a; b += 10; a += 10; c += 10; return 0; }
對于這塊報錯問題:是因為c是不可修改的
(2)引用常量
int main() { int a = 10; const int b =20; int& x = a; int& y = b; //error 不安全 const int& y = b; //ok const int& z =10; //ok return 0; }
(3)引用字面常量
引用字面常量時,分兩步走,首先定義一個臨時量 去引用臨時量 不是引用真實的字面常量10。
int main() { int a = 10; const int& z =10; //ok //int tmp =10; //const int &z = tmp; return 0; }
數組引用
在引用數組時,必須知道數組的大小
int main() { int a = 10; int b = 10; int ar[5] = { 1,2,3,4,5 }; int& x = ar[0]; //ok int(&x)[5] = ar; //ok 沒有[5]無法編譯通過 return 0; }
指針引用
引用既然就是一個變量,那我同樣也可以給指針變量取一個別名
int main() { int a = 100; int *p = &a; int * &rp = p; cout << a << endl; cout << *p << endl; cout << *rp << endl; //這里為什么要將*放在前面,因為p的類型是 int * 作為一個整體哦!! cout << p << endl; cout << rp << endl; getchar(); return 0; } /* 100 100 100 012FF84C 012FF84C */
我們發(fā)現(xiàn)這里的指針變量p和它的引用(別名)rp是完全一樣的。但是由于引用的目的跟指針的目的是類似的,所以一般不需要對指針再起別名了。
原文鏈接:https://blog.csdn.net/weixin_56935264/article/details/124669712
相關推薦
- 2023-10-16 清理linux日志
- 2022-10-18 pandas重復行刪除操作df.drop_duplicates和df.duplicated的區(qū)別_p
- 2022-12-14 PostgreSql?JDBC事務操作方法詳解_PostgreSQL
- 2022-10-21 Python?NumPy教程之數組的基本操作詳解_python
- 2024-01-10 Springboot應用中@EntityScan和@EnableJpaRepositories的用法
- 2022-11-14 Git暫存區(qū)的意義或git add的意義
- 2022-08-26 Python實現(xiàn)雙向RNN與堆疊的雙向RNN的示例代碼_python
- 2022-11-09 Sql?Server?"用戶登錄失敗,錯誤編18456"的解決過程_MsSql
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支