C++?引用和指針的區(qū)別對比分析
在 C++ 中,指針(Pointer)和引用(Reference)都用于間接訪問變量,但是它們在語法和語義上都有顯著的差異。指針是一個(gè)變量,它可以保存另一個(gè)變量的內(nèi)存地址;引用是另一個(gè)變量的別名,由編譯器進(jìn)行處理,使用時(shí)與使用原變量無異。
指針和引用使用的一些差異如下:
初始化
指針:可以先定義后賦值,也可以指向不同的對象。
int a = 10, b = 20; int* p = &a; p = &b; // 改變指向
引用:必須在定義時(shí)就進(jìn)行初始化,綁定到一個(gè)特定的對象,并且不能綁定到其他的對象。
int a = 10, b = 20; int& r = a; r = b; // 修改的是 a 的值,而不是重新綁定,等價(jià)于 a=b
可空性
指針:可以被定義為 nullptr,表示不指向任何對象。
引用:必須綁定有效對象,不能為 null,否則會產(chǎn)生為定義的行為。
內(nèi)存占用
指針:由于存儲的是內(nèi)存地址,因此需要占用內(nèi)存空間,一般為 32 bit 或 64 bit。
引用:語義上不占用內(nèi)存空間,實(shí)際可能由編譯器實(shí)現(xiàn)為一個(gè)隱藏指針。
這里我們參考一篇博客: C++ 中指針和引用的區(qū)別。
參考以下使用引用和指針實(shí)現(xiàn)的 swap 函數(shù)。
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}引用版本 swap() 函數(shù)的匯編代碼如下:
# void swap(int &a, int &b)
__Z4swapRiS_: ## @_Z4swapRiS_
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
movq %rdi, -8(%rbp) # 傳入的第一個(gè)參數(shù)存放到%rbp-8 (應(yīng)該是采用的寄存器傳參,而不是常見的壓棧)
movq %rsi, -16(%rbp) # 第二個(gè)參數(shù) 存放到 %rbp-16
movq -8(%rbp), %rsi # 第一個(gè)參數(shù)賦給 rsi
movl (%rsi), %eax # 以第一個(gè)參數(shù)為地址取出值賦給eax,取出*a暫存寄存器
movl %eax, -20(%rbp) # temp = a
movq -16(%rbp), %rsi # 將第二個(gè)參數(shù)重復(fù)上面的
movl (%rsi), %eax
movq -8(%rbp), %rsi
movl %eax, (%rsi) # a = b
movl -20(%rbp), %eax # eax = temp
movq -16(%rbp), %rsi
movl %eax, (%rsi) # b = temp
popq %rbp
retq
.cfi_endproc
## -- End function指針版本 swap() 函數(shù)的匯編代碼如下:
# void swap(int *a, int *b)
__Z4swapPiS_: ## @_Z4swapPiS_
.cfi_startproc
## %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
movq %rdi, -8(%rbp)
movq %rsi, -16(%rbp)
movq -8(%rbp), %rsi
movl (%rsi), %eax
movl %eax, -20(%rbp)
movq -16(%rbp), %rsi
movl (%rsi), %eax
movq -8(%rbp), %rsi
movl %eax, (%rsi)
movl -20(%rbp), %eax
movq -16(%rbp), %rsi
movl %eax, (%rsi)
popq %rbp
retq
.cfi_endproc
## -- End function可以看到,兩個(gè)函數(shù)的匯編代碼幾乎完全一致。引用所賦的初值也就是綁定對象的內(nèi)存地址,訪問和修改對象內(nèi)容也是通過這個(gè)內(nèi)存地址完成的。
既然引用和指針的底層實(shí)現(xiàn)機(jī)制幾乎沒有區(qū)別,那么為什么我們需要使用引用呢?我認(rèn)為有以下兩點(diǎn):
- 便捷性:能夠讓使用者使用引用與使用對象本身一致,由編譯器自動(dòng)進(jìn)行取地址、解引用的操作。
- 安全性:引用必須初始化,且不能更換綁定,避免了懸空指針和野指針的問題,這在接口設(shè)計(jì)中更可靠,要求必須傳入合法的對象。
到此這篇關(guān)于C++ 引用和指針的區(qū)別對比分析的文章就介紹到這了,更多相關(guān)C++ 引用和指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)用庫之DNS解析的實(shí)現(xiàn)
DNS解析是一種將域名轉(zhuǎn)換為相應(yīng)的IP地址的過程,本文主要介紹了C++實(shí)用庫之DNS解析的實(shí)現(xiàn),實(shí)現(xiàn)了快速、準(zhǔn)確的域名到IP地址的轉(zhuǎn)換,感興趣的可以了解一下2025-03-03
C++中虛繼承時(shí)的構(gòu)造函數(shù)示例詳解
在虛繼承中,虛基類是由最終的派生類初始化的,換句話說,最終派生類的構(gòu)造函數(shù)必須要調(diào)用虛基類的構(gòu)造函數(shù),這跟普通繼承不同,在普通繼承中,派生類構(gòu)造函數(shù)中只能調(diào)用直接基類的構(gòu)造函數(shù),不能調(diào)用間接基類的,所以本文將通過代碼示例給大家介紹一下C++虛繼承構(gòu)造函數(shù)2023-09-09
C語言之把數(shù)組名作函數(shù)參數(shù)的四種情況說明
這篇文章主要介紹了C語言之把數(shù)組名作函數(shù)參數(shù)的四種情況說明,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
C語言實(shí)現(xiàn)直角坐標(biāo)轉(zhuǎn)換為極坐標(biāo)的方法
這篇文章主要介紹了C語言實(shí)現(xiàn)直角坐標(biāo)轉(zhuǎn)換為極坐標(biāo)的方法,涉及C語言進(jìn)行三角函數(shù)與數(shù)值運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-09-09
NDK 數(shù)據(jù)結(jié)構(gòu)之隊(duì)列與棧等的實(shí)現(xiàn)
這篇文章主要介紹了NDK 數(shù)據(jù)結(jié)構(gòu)之隊(duì)列與棧等的實(shí)現(xiàn)的相關(guān)資料,希望通過本文大家能理解掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10

