c++指針參數(shù)傳遞和引用參數(shù)傳遞的區(qū)別解析
c++指針參數(shù)傳遞和引用參數(shù)傳遞的區(qū)別
1) 指針參數(shù)傳遞本質(zhì)上是值傳遞,它所傳遞的是一個地址值。
值傳遞過程中,被調(diào)函數(shù)的形式參數(shù)作為被調(diào)函數(shù)的局部變量處理,會在棧中開辟內(nèi)存空間以存放由主調(diào)函數(shù)傳遞進來的實參值,從而形成了實參的一個副本(替身)。
值傳遞的特點是,被調(diào)函數(shù)對形式參數(shù)的任何操作都是作為局部變量進行的,不會影響主調(diào)函數(shù)的實參變量的值(形參指針變了,實參指針不會變)。
2) 引用參數(shù)傳遞過程中,被調(diào)函數(shù)的形式參數(shù)也作為局部變量在棧中開辟了內(nèi)存空間,但是這時存放的是由主調(diào)函數(shù)放進來的實參變量的地址。
被調(diào)函數(shù)對形參(本體)的任何操作都被處理成間接尋址,即通過棧中存放的地址訪問主調(diào)函數(shù)中的實參變量(根據(jù)別名找到主調(diào)函數(shù)中的本體)。
因此,被調(diào)函數(shù)對形參的任何操作都會影響主調(diào)函數(shù)中的實參變量。
3) 引用傳遞和指針傳遞是不同的,雖然他們都是在被調(diào)函數(shù)??臻g上的一個局部變量,但是任何對于引用參數(shù)的處理都會通過一個間接尋址的方式操作到主調(diào)函數(shù)中的相關變量。
而對于指針傳遞的參數(shù),如果改變被調(diào)函數(shù)中的指針地址,它將應用不到主調(diào)函數(shù)的相關變量。如果想通過指針參數(shù)傳遞來改變主調(diào)函數(shù)中的相關變量(地址),那就得使用指向指針的指針或者指針引用。
4) 從編譯的角度來講,程序在編譯時分別將指針和引用添加到符號表上,符號表中記錄的是變量名及變量所對應地址。
指針變量在符號表上對應的地址值為指針變量的地址值,而引用在符號表上對應的地址值為引用對象的地址值(與實參名字不同,地址相同)。
符號表生成之后就不會再改,因此指針可以改變其指向的對象(指針變量中的值可以改),而引用對象則不能修改。
從根本上將,指針和引用的效果類似,但是c++引入引用是為了方便運算符重載,比如string類重載運算符[ ]
class string{ //... char& operato[] (int index); //返回一個引用 }
c++不直接用引用代替指針,是為了兼容c語言
需要返回函數(shù)內(nèi)局部變量的內(nèi)存的時候用指針。使用指針傳參需要開辟內(nèi)存,用完要記得釋放指針,不然會內(nèi)存泄漏。而返回局部變量的引用是沒有意義的
對??臻g大小比較敏感(比如遞歸)的時候使用引用。使用引用傳遞不需要創(chuàng)建臨時變量,開銷要更小
類對象作為參數(shù)傳遞的時候使用引用,這是C++類對象傳遞的標準方式
c++ 引用傳參和指針傳參的區(qū)別
概念
- 指針從本質(zhì)上講是一個變量,變量的值是另一個變量的地址,指針在邏輯上是獨立的,它可以被改變的,包括指針變量的值(所指向的地址)和指針變量的值對應的內(nèi)存中的數(shù)據(jù)(所指向地址中所存放的數(shù)據(jù))。
- 引用從本質(zhì)上講是一個別名,是另一個變量的同義詞,它在邏輯上不是獨立的,它的存在具有依附性,所以引用必須在一開始就被初始化(先有這個變量,這個實物,這個實物才能有別名),而且其引用的對象在其整個生命周期中不能被改變,即自始至終只能依附于同一個變量(初始化的時候代表的是誰的別名,就一直是誰的別名,不能變)。
區(qū)別
指針 | 變量,獨立,可變,可空,替身,無類型檢查 |
---|---|
引用 | 別名,依賴,不變,非空,本體,有類型檢查 |
- 指針參數(shù)傳遞本質(zhì)上是值傳遞,它所傳遞的是一個地址值。值傳遞過程中,被調(diào)函數(shù)的形式參數(shù)作為被調(diào)函數(shù)的局部變量處理,會在棧中開辟內(nèi)存空間以存放由主調(diào)函數(shù)傳遞進來的實參值,從而形成了實參的一個副本(替身)。值傳遞的特點是,被調(diào)函數(shù)對形式參數(shù)的任何操作都是作為局部變量進行的,不會影響主調(diào)函數(shù)的實參變量的值(形參指針變了,實參指針不會變)。
- 引用參數(shù)傳遞過程中,被調(diào)函數(shù)的形式參數(shù)也作為局部變量在棧中開辟了內(nèi)存空間,但是這時存放的是由主調(diào)函數(shù)放進來的實參變量的地址。被調(diào)函數(shù)對形參(本體)的任何操作都被處理成間接尋址,即通過棧中存放的地址訪問主調(diào)函數(shù)中的實參變量(根據(jù)別名找到主調(diào)函數(shù)中的本體)。因此,被調(diào)函數(shù)對形參的任何操作都會影響主調(diào)函數(shù)中的實參變量。
- 引用傳遞和指針傳遞是不同的,雖然他們都是在被調(diào)函數(shù)??臻g上的一個局部變量,但是任何對于引用參數(shù)的處理都會通過一個間接尋址的方式操作到主調(diào)函數(shù)中的相關變量。而對于指針傳遞的參數(shù),如果改變被調(diào)函數(shù)中的指針地址,它將應用不到主調(diào)函數(shù)的相關變量。如果想通過指針參數(shù)傳遞來改變主調(diào)函數(shù)中的相關變量(地址),那就得使用指向指針的指針或者指針引用。
- 從編譯的角度來講,程序在編譯時分別將指針和引用添加到符號表上,符號表中記錄的是變量名及變量所對應地址。指針變量在符號表上對應的地址值為指針變量的地址值,而引用在符號表上對應的地址值為引用對象的地址值(與實參名字不同,地址相同)。符號表生成之后就不會再改,因此指針可以改變其指向的對象(指針變量中的值可以改),而引用對象則不能修改。
以上內(nèi)容來源網(wǎng)絡
如何使用
如果我們編程只是為了做一些簡單的工作,不想在技術上有什么質(zhì)的突破,那么使用指針就夠了。這樣做的問題就是,你寫的代碼很容易出bug??墒牵绻覀兿胍獙++有更深的了解,那么一定要區(qū)分指針傳參與引用傳參的區(qū)別。
使用指針傳遞參數(shù),是為了避免拷貝副本,從而提高程序執(zhí)行效率,大所數(shù)初學者(也包括我)都習慣使用指針傳遞參數(shù),因為還沒有建立起引用的概念,我們以為指針就是引用,殊不知,引用的內(nèi)涵比指針更豐富。因為用的少,所以對引用的概念懵懵懂懂。其實有經(jīng)驗的程序員在傳遞參數(shù)時很少使用指針。下面通過代碼來說明我們?yōu)槭裁匆褂靡脗鲄?,放棄指針傳參?/p>
- 首先定義一個結(jié)構(gòu)體
struct ST { public: int num; string name; ST(int num, string name) { this->num = num; this->name = name; } void putInfo() { cout << "學號:" << num << endl; cout << "姓名:" << name << endl; } };
1.使用指針傳參
void dealProcess(ST* st) { ST *newST =new ST(320, "小明"); st = newST;//為臨時指針變量賦予了新值,已和輸入脫離了聯(lián)系。 } int main() { int num = 1; ST st1(310, "小紅"); dealProcess(&st1); st1.putInfo(); system("pause"); return 0; }
輸出結(jié)果
使用指針傳參,想返回處理后的結(jié)果,但是我們得到的結(jié)果卻和預想的不一致。因為在處理的過程中,形參的地址發(fā)生了變化,和輸入脫離了聯(lián)系。
正確的寫法:
void dealProcess(ST* st) { ST *newST =new ST(320, "小明"); *st = *newST; }
嚴謹?shù)膶懛ǎǖ缓啙崳?/p>
void dealProcess(ST* const st)//指定形參為常量指針,不能修改值 { ST *newST =new ST(320, "小明"); *st=*newsT; st = newST; //編譯錯誤,不允許修改常量 }
void dealProcess(ST* const st)
等價于void dealProcess(ST* st const)
2.既嚴謹又簡潔的寫法,使用引用
void dealProcess(ST& st) { ST newST(320, "小明"); st = newST; &st=&newsT;//編譯錯誤,不允許改變輸入的地址 } int main() { int num = 1; ST st1(310, "小紅"); dealProcess(st1); st1.putInfo(); system("pause"); return 0; }
3.如果僅僅是使用輸入的值,應該限定輸入為常量
首選是使用引用
void dealProcess(const ST& st) { ST newST(0,""); newST.putInfo(); //輸入的值不允許被改變 st = newST; //編譯錯誤,只允許使用輸入,不允許改變輸入的值 &st = &newsT;//編譯錯誤,不允許改變輸入的地址 //使用輸入的值, newST = st; newST.putInfo(); } int main() { int num = 1; ST st1(310, "小紅"); dealProcess(st1); system("pause"); return 0; }
如果一定要使用指針,等價代碼如下
void dealProcess(const ST* const st) { ST newST(0,""); newST.putInfo(); //使用輸入的值 newST = *st; newST.putInfo(); } int main() { int num = 1; ST st1(310, "小紅"); dealProcess(&st1); system("pause"); return 0; }
到此這篇關于c++指針參數(shù)傳遞和引用參數(shù)傳遞的區(qū)別的文章就介紹到這了,更多相關c++指針參數(shù)傳遞和引用參數(shù)傳遞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++中使用哈希表(unordered_map)的一些常用操作方法
C++標準庫中使用的unordered_map底層實現(xiàn)是哈希表,下面這篇文章主要給大家介紹了關于C++中使用哈希表(unordered_map)的一些常用操作方法,需要的朋友可以參考下2022-03-03c++實現(xiàn)逐行讀取配置文件寫入內(nèi)存的示例
這篇文章主要介紹了c++實現(xiàn)逐行讀取配置文件寫入內(nèi)存的示例,需要的朋友可以參考下2014-05-05C語言實現(xiàn)簡易通訊錄(靜態(tài)版本)的代碼分享
這篇文章主要為大家詳細介紹了如何錄音C語言實現(xiàn)一個簡易的通訊錄(靜態(tài)版本),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-10-10排列和組合算法的實現(xiàn)方法_C語言經(jīng)典案例
下面小編就為大家?guī)硪黄帕泻徒M合算法的實現(xiàn)方法_C語言經(jīng)典案例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09