(1)形參是實參的拷貝(這句話說明形參和實參是兩個實體),改變形參的值並不會影響外部實參的值。ios
(2)從被調用函數的角度來講,值傳遞是單向的(實參->形參),參數的值只能傳入,不能傳出。當函數內部須要修改參數,而且不但願這個改變影響調用者時,採用值傳遞。函數
(1)指針從本質上講就是存放變量地址的一個變量,在邏輯上是獨立的,它能夠被改變,包括其所指向的地址的改變和其指向的地址中所存放的數據的改變。spa
(2)形參爲指向實參地址的指針,當對形參的指向操做時,就至關於對實參自己進行的操做。指針
(1)引用是一個別名,它在邏輯上不是獨立的,它的存在具備依附性,因此引用必須在一開始就被初始化,並且其引用的對象在其整個生命週期中是不能被改變的(自始至終只能依附於同一個變量)。code
(2)形參至關因而實參的「別名」,對形參的操做其實就是對實參的操做,在引用傳遞過程當中,被調函數的形式參數雖然也做爲局部變量在棧中開闢了內存空間,可是這時存放的是由主調函數放進來的實參變量的地址。對象
(3)被調函數對形參的任何操做都被處理成間接尋址,即經過棧中存放的地址訪問主調函數中的實參變量。正由於如此,被調函數對形參作的任何操做都影響了主調函數中的實參變量。生命週期
#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+1; } int main(){ int n=10; 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; }
運行結果以下(不一樣的機器可能會有所差異):內存
分析:io
能夠看出,實參的地址爲0x22ff44class
採用值傳遞的時候,函數操做的地址是0x22ff20並非實參自己,因此對它進行操做並不能改變實參的值。
再看引用傳遞,操做地址就是實參地址 ,只是至關於實參的一個別名,對它的操做就是對實參的操做。
接下來是指針傳遞,也可發現操做地址是實參地址。
a)引用被建立的同時必須被初始化(指針則能夠在任什麼時候候被初始化)。
b)不能有NULL引用,引用必須與合法的存儲單元關聯(指針則能夠是NULL)。
c)一旦引用被初始化,就不能改變引用的關係(指針則能夠隨時改變所指的對象)。
a)指針傳遞參數本質上是值傳遞的方式,它所傳遞的是一個地址值。值傳遞過程當中,被調函數的形式參數做爲被調函數的局部變量處理,即在棧中開闢了內存空間以存放由主調函數放進來的實參的值,從而成爲了實參的一個副本。
b)值傳遞的特色是被調函數對形式參數的任何操做都是做爲局部變量進行,不會影響主調函數的實參變量的值。(這裏是在說實參指針自己的地址值不會變)
a)函數內部修改參數而且但願改動影響調用者。對比指針/引用傳遞能夠將改變由形參「傳給」實參(實際上就是直接在實參的內存上修改,不像值傳遞將實參的值拷貝到另外的內存地址中才修改)。
b)另一種用法是:當一個函數實際須要返回多個值,而只能顯式返回一個值時,能夠將另外須要返回的變量以指針/引用傳遞給函數,這樣在函數內部修改而且返回後,調用者能夠拿到被修改事後的變量,也至關於一個隱式的返回值傳遞吧。