1.概念說明
值傳遞:
形參是實參的拷貝,改變形參的值并不會影響外部實參的值。從被調用函數的角度來說,值傳遞是單向的(實參->形參),參數的值隻能傳入,不能傳出。當函數内部需要修改參數,并且不希望這個改變影響調用者時,采用值傳遞。
指針傳遞:
形參為指向實參位址的指針,當對形參的指向操作時,就相當于對實參本身進行的操作
引用傳遞:
形參相當于是實參的“别名”,對形參的操作其實就是對實參的操作,在引用傳遞過程中,被調函數的形式參數雖然也作為局部變量在棧中開辟了記憶體空間,但是這時存放的是由主調函數放進來的實參變量的位址。被調函數對形參的任何操作都被處理成間接尋址,即通過棧中存放的位址通路主調函數中的實參變量。正因為如此,被調函數對形參做的任何操作都影響了主調函數中的實參變量。
2.代碼解析
#include<iostream>
using namespace std;
//值傳遞
void change1(int n){
cout<<"值傳遞--函數操作位址"<<&n<<endl; //顯示的是拷貝的位址而不是源位址
n++;
}
//引用傳遞
void change2(int & n){
cout<<"引用傳遞--函數操作位址"<<&n<<endl;
n++;
}
//指針傳遞
void change3(int *n){
cout<<"指針傳遞--函數操作位址 "<<n<<endl;
*n=*n+;
}
int main(){
int n=;
cout<<"實參的位址"<<&n<<endl;
change1(n);
cout<<"after change1() n="<<n<<endl;
change2(n);
cout<<"after change2() n="<<n<<endl;
change3(&n);
cout<<"after change3() n="<<n<<endl;
return true;
}
3.深度剖析
知識點補充:指針和引用的相同點和不同點:
★概念:
●指針從本質上講就是存放變量位址的一個變量,在邏輯上是獨立的,它可以被改變,包括其所指向的位址的改變和其指向的位址中所存放的資料的改變;
●而引用是一個别名,它在邏輯上不是獨立的,它的存在具有依附性,是以引用必須在一開始就被初始化,而且其引用的對象在其整個生命周期中是不能被改變的(自始至終隻能依附于同一個變量)。
★相同點:
●都是位址的概念;
指針指向一塊記憶體,它的内容是所指記憶體的位址;而引用則是某塊記憶體的别名。
★不同點:
●指針是一個實體,而引用僅是個别名;
●引用隻能在定義時被初始化一次,之後不可變;指針可變;引用“從一而終”,指針可以“見異思遷”;
●引用沒有const,指針有const,const的指針不可變;(具體指沒有int& const a這種形式,而const int& a是有 的, 前者指引用本身即别名不可以改變,這是當然的,是以不需要這種形式,後者指引用所指的值不可以改變)
●引用不能為空,必須在定義的時候同時進行初始化。指針可以為空,任何時候初始化都可;
●“sizeof 引用”得到的是所指向的變量(對象)的大小,而“sizeof 指針”得到的是指針本身的大小;
●指針和引用的自增(++)運算意義不一樣;
●引用是類型安全的,而指針不是 (引用比指針多了類型檢查)
★編譯角度解析:
程式在編譯時分别将指針和引用添加到符号表上,符号表上記錄的是變量名及變量所對應位址。指針變量在符号表上對應的位址值為指針變量的位址值,而引用在符号表上對應的位址值為引用對象的位址值。符号表生成後就不會再改,是以指針可以改變其指向的對象(指針變量中的值可以改),而引用對象則不能修改。
知識點補充:指針傳遞和引用傳遞适用情形
函數内部修改參數并且希望改動影響調用者。對比指針/引用傳遞可以将改變由形參“傳給”實參(實際上就是直接在實參的記憶體上修改,不像值傳遞将實參的值拷貝到另外的記憶體位址中才修改)。
另外一種用法是:當一個函數實際需要傳回多個值,而隻能顯式傳回一個值時,可以将另外需要傳回的變量以指針/引用傳遞給函數,這樣在函數内部修改并且傳回後,調用者可以拿到被修改過後的變量,也相當于一個隐式的傳回值傳遞吧。
知識點補充:指針傳遞和引用傳遞的差別:
指針傳遞參數本質上是值傳遞的方式,它所傳遞的是一個位址值。值傳遞過程中,被調函數的形式參數作為被調函數的局部變量處理,即在棧中開辟了記憶體空間以存放由主調函數放進來的實參的值,進而成為了實參的一個副本。值傳遞的特點是被調函數對形式參數的任何操作都是作為局部變量進行,不會影響主調函數的實參變量的值。(這裡是在說實參指針本身的位址值不會變,但是指針指向的空間存儲的内容是否發生變化是無法确定的)。
而在引用傳遞過程中,被調函數的形式參數雖然也作為局部變量在棧中開辟了記憶體空間,但是這時存放的是由主調函數放進來的實參變量的位址。被調函數對形參的任何操作都被處理成間接尋址,即通過棧中存放的位址通路主調函數中的實參變量。正因為如此,被調函數對形參做的任何操作都影響了主調函數中的實參變量。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczLcVmds92czlGZvwVP9EUTDZ0aRJkSwk0LcxGbpZ2LcBDM08CXlpXazRnbvZ2LcRlMMVDT2EWNvwFdu9mZvwVPRhVWvR2MaVHbyEmb1IjY2hnMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39TM5cTM0cDNzIjNwkDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
引用傳遞和指針傳遞是不同的,雖然它們都是在被調函數棧空間上的一個局部變量,但是任何對于引用參數的處理都會通過一個間接尋址的方式操作到主調函數中的相關變量。而對于指針傳遞的參數,如果改變被調函數中的指針位址,它将影響不到主調函數的相關變量。如果想通過指針參數傳遞來改變主調函數中的相關變量,那就得使用指向指針的指針,或者指針引用。
參考文獻:
[1]http://xinklabi.iteye.com/blog/653643
[2]https://www.cnblogs.com/dingxiaoqiang/p/8012578.html
[3]https://blog.csdn.net/bitlxlx/article/details/74781780