c++引用傳參和指針傳參的區(qū)別及說(shuō)明
概念
指針從本質(zhì)上講是一個(gè)變量,變量的值是另一個(gè)變量的地址,指針在邏輯上是獨(dú)立的,它可以被改變的,包括指針變量的值(所指向的地址)和指針變量的值對(duì)應(yīng)的內(nèi)存中的數(shù)據(jù)(所指向地址中所存放的數(shù)據(jù))。
引用從本質(zhì)上講是一個(gè)別名,是另一個(gè)變量的同義詞,它在邏輯上不是獨(dú)立的,它的存在具有依附性,所以引用必須在一開(kāi)始就被初始化(先有這個(gè)變量,這個(gè)實(shí)物,這個(gè)實(shí)物才能有別名),而且其引用的對(duì)象在其整個(gè)生命周期中不能被改變,即自始至終只能依附于同一個(gè)變量(初始化的時(shí)候代表的是誰(shuí)的別名,就一直是誰(shuí)的別名,不能變)。
區(qū)別
指針 | 變量,獨(dú)立,可變,可空,替身,無(wú)類(lèi)型檢查 |
---|---|
引用 | 別名,依賴(lài),不變,非空,本體,有類(lèi)型檢查 |
指針參數(shù)傳遞本質(zhì)上是值傳遞,它所傳遞的是一個(gè)地址值。值傳遞過(guò)程中,被調(diào)函數(shù)的形式參數(shù)作為被調(diào)函數(shù)的局部變量處理,會(huì)在棧中開(kāi)辟內(nèi)存空間以存放由主調(diào)函數(shù)傳遞進(jìn)來(lái)的實(shí)參值,從而形成了實(shí)參的一個(gè)副本(替身)。值傳遞的特點(diǎn)是,被調(diào)函數(shù)對(duì)形式參數(shù)的任何操作都是作為局部變量進(jìn)行的,不會(huì)影響主調(diào)函數(shù)的實(shí)參變量的值(形參指針變了,實(shí)參指針不會(huì)變)。
引用參數(shù)傳遞過(guò)程中,被調(diào)函數(shù)的形式參數(shù)也作為局部變量在棧中開(kāi)辟了內(nèi)存空間,但是這時(shí)存放的是由主調(diào)函數(shù)放進(jìn)來(lái)的實(shí)參變量的地址。被調(diào)函數(shù)對(duì)形參(本體)的任何操作都被處理成間接尋址,即通過(guò)棧中存放的地址訪問(wèn)主調(diào)函數(shù)中的實(shí)參變量(根據(jù)別名找到主調(diào)函數(shù)中的本體)。因此,被調(diào)函數(shù)對(duì)形參的任何操作都會(huì)影響主調(diào)函數(shù)中的實(shí)參變量。
引用傳遞和指針傳遞是不同的,雖然他們都是在被調(diào)函數(shù)??臻g上的一個(gè)局部變量,但是任何對(duì)于引用參數(shù)的處理都會(huì)通過(guò)一個(gè)間接尋址的方式操作到主調(diào)函數(shù)中的相關(guān)變量。而對(duì)于指針傳遞的參數(shù),如果改變被調(diào)函數(shù)中的指針地址,它將應(yīng)用不到主調(diào)函數(shù)的相關(guān)變量。如果想通過(guò)指針參數(shù)傳遞來(lái)改變主調(diào)函數(shù)中的相關(guān)變量(地址),那就得使用指向指針的指針或者指針引用。
從編譯的角度來(lái)講,程序在編譯時(shí)分別將指針和引用添加到符號(hào)表上,符號(hào)表中記錄的是變量名及變量所對(duì)應(yīng)地址。指針變量在符號(hào)表上對(duì)應(yīng)的地址值為指針變量的地址值,而引用在符號(hào)表上對(duì)應(yīng)的地址值為引用對(duì)象的地址值(與實(shí)參名字不同,地址相同)。符號(hào)表生成之后就不會(huì)再改,因此指針可以改變其指向的對(duì)象(指針變量中的值可以改),而引用對(duì)象則不能修改。
以上內(nèi)容來(lái)源網(wǎng)絡(luò)
如何使用
- 如果我們編程只是為了做一些簡(jiǎn)單的工作,不想在技術(shù)上有什么質(zhì)的突破,那么使用指針就夠了。
- 這樣做的問(wèn)題就是,你寫(xiě)的代碼很容易出bug。
- 可是,如果我們想要對(duì)c++有更深的了解,那么一定要區(qū)分指針傳參與引用傳參的區(qū)別。
使用指針傳遞參數(shù),是為了避免拷貝副本,從而提高程序執(zhí)行效率,大所數(shù)初學(xué)者(也包括我)都習(xí)慣使用指針傳遞參數(shù),因?yàn)檫€沒(méi)有建立起引用的概念,我們以為指針就是引用,殊不知,引用的內(nèi)涵比指針更豐富。因?yàn)橛玫纳伲詫?duì)引用的概念懵懵懂懂。其實(shí)有經(jīng)驗(yàn)的程序員在傳遞參數(shù)時(shí)很少使用指針。下面通過(guò)代碼來(lái)說(shuō)明我們?yōu)槭裁匆褂靡脗鲄?,放棄指針傳參?/p>
首先定義一個(gè)結(jié)構(gòu)體
struct ST { public: int num; string name; ST(int num, string name) { this->num = num; this->name = name; } void putInfo() { cout << "學(xué)號(hào):" << num << endl; cout << "姓名:" << name << endl; } };
1.使用指針傳參
void dealProcess(ST* st) { ST *newST =new ST(320, "小明"); st = newST;//為臨時(shí)指針變量賦予了新值,已和輸入脫離了聯(lián)系。 } int main() { int num = 1; ST st1(310, "小紅"); dealProcess(&st1); st1.putInfo(); system("pause"); return 0; }
輸出結(jié)果
使用指針傳參,想返回處理后的結(jié)果,但是我們得到的結(jié)果卻和預(yù)想的不一致。因?yàn)樵谔幚淼倪^(guò)程中,形參的地址發(fā)生了變化,和輸入脫離了聯(lián)系。
正確的寫(xiě)法:
void dealProcess(ST* st) { ST *newST =new ST(320, "小明"); *st = *newST; }
嚴(yán)謹(jǐn)?shù)膶?xiě)法(但不簡(jiǎn)潔)
void dealProcess(ST* const st)//指定形參為常量指針,不能修改值 { ST *newST =new ST(320, "小明"); *st=*newsT; st = newST; //編譯錯(cuò)誤,不允許修改常量 }
void dealProcess(ST* const st)
等價(jià)于void dealProcess(ST* st const)
2.既嚴(yán)謹(jǐn)又簡(jiǎn)潔的寫(xiě)法,使用引用
void dealProcess(ST& st) { ST newST(320, "小明"); st = newST; &st=&newsT;//編譯錯(cuò)誤,不允許改變輸入的地址 } int main() { int num = 1; ST st1(310, "小紅"); dealProcess(st1); st1.putInfo(); system("pause"); return 0; }
3.如果僅僅是使用輸入的值,應(yīng)該限定輸入為常量
首選是使用引用
void dealProcess(const ST& st) { ST newST(0,""); newST.putInfo(); //輸入的值不允許被改變 st = newST; //編譯錯(cuò)誤,只允許使用輸入,不允許改變輸入的值 &st = &newsT;//編譯錯(cuò)誤,不允許改變輸入的地址 //使用輸入的值, newST = st; newST.putInfo(); } int main() { int num = 1; ST st1(310, "小紅"); dealProcess(st1); system("pause"); return 0; }
如果一定要使用指針,等價(jià)代碼如下
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; }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
c語(yǔ)言程序設(shè)計(jì)文件操作方法示例(CreateFile和fopen)
c主要的文件操作函數(shù)有:CreateFile,CloseHandle,ReadFile,WriteFile,SetFilePointer,GetFileSize。其中的讀寫(xiě)操作是以字符為單位,獲得文件大小也是以字符為單位。2013-12-12C++生成dll和調(diào)用dll的方法實(shí)例
C++生成dll和調(diào)用dll的方法實(shí)例,需要的朋友可以參考一下2013-03-03vscode cmake compilers配置路徑的實(shí)現(xiàn)
本文主要介紹了vscode cmake compilers配置路徑的實(shí)現(xiàn),文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-03-03C++實(shí)現(xiàn)四則運(yùn)算器(帶括號(hào))
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)四則運(yùn)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11