概念
首先從概念上來講一下這幾種函數傳參方式及區別:
一、值傳遞:形參是實參的拷貝,改變函數形參的值並不會影響外部實參的值,這是最經常使用的一種傳參方法,也是最簡單的一種傳參方法,只須要傳遞參數,返回值那是return考慮的;
二、指針傳遞:指針傳遞參數從本質上來講也是值傳遞,它傳遞的是一個地址。【值傳遞過程當中,被調函數的形參做爲被調函數的局部變量來處理,即在函數內的棧中開闢內存空間以存放由主調函數放進來的實參的值,從而成了實參的一個副本(記住這個,函數內參數的是實參的副本)】。因爲指針傳遞的是外部實參的地址,當被調函數的形參值發生改變時,天然外部實參值也發生改變。
三、引用傳遞:被調函數的形參雖然也做爲局部變量在棧中開闢了內存空間,可是棧中存放的是由主調函數放進的實參變量的地址。被調函數對形參的任何操做都被處理成間接尋址,即經過棧中存放的地址訪問主調函數中實參變量(實參和形參經過引用,合二爲一,說白點就是:一我的,有兩個名字那種;後面想會詳細說)。所以,形參的任何改動都會直接影響到實參。
實例
先從簡單的例子開始:
- 值傳遞:例子略過。
- 指針傳遞:
- void swap(int *a,int *b)
- {
- int temp;
- temp=*a;
- *a=*b;
- *b=temp;
- cout<<"a=" <<a<<" ,"<<"b="<<b<<endl;
- cout<<"*a=" <<*a<<" ,"<<"*b="<<*b<<endl;
- cout<<"&a=" <<&a<<" ,"<<"&b="<<&b<<endl;
- }
(剛上大學的時候就接觸過的例子,交換值)調用:
- int main(){
- int x=1;
- int y=2;
- cout<<"x=" <<x<<" ,"<<"y="<<y<<endl;
- cout<<"&x=" <<&x<<" ,"<<"&y="<<&y<<endl;
- swap(&x,&y);
- }
必定要記住這種調用方式
如指針傳遞的概念上所述,傳地址給形參。
形如:int *a = &x;//用於指針傳遞,a有本身獨立的內存地址,存儲的內容是x的地址,*a是存x的值。
輸出結果:
傳入值的各變量的初始狀態(地址狀態):
從上圖關係能夠知道:a(b)是一個指向外部實參地址的指針,*a(*b)是指針的內容,若是改變了*a(*b)也必然致使外部實參的改變。
交換後:
*a=2,*b=1;
這樣的結果是因爲a或者b指針指向x或者y的地址的緣故,所以因爲*a,*b值得交換致使外部實參發生變化。
思考一下,下面的操做可否實現值得變化?
簡單測試代碼:
- int change(char* name){
- cout<<"*******CHANGE--BEFORE******"<<endl;
- cout<<"name=" <<name<<endl;
- cout<<"*name=" <<&name<<endl;
- name="alter";
- cout<<"*******CHANGE--AFTER********"<<endl;
- cout<<"name=" <<name<<endl;
- cout<<"*name=" <<&name<<endl;
- return 1;
- }
- int main()
- {
- char *str = "this is a test";
-
- cout<<"******MAIN--BEFORE*****"<<endl;
- cout<<"str=" <<str<<endl;
- cout<<"*str=" <<&str<<endl;
- change(str);
- cout<<"*****MAIN--AFTER*****"<<endl;
- cout<<"str=" <<str<<endl;
- cout<<"*str=" <<&str<<endl;
- return 1;
- }
執行結果:
![](http://static.javashuo.com/static/loading.gif)
(打印的輸出的時候,有點錯誤,*str應該爲 &str)
從結果中發現,並未達到改變值得效果,爲何?這個測試代碼和本文開始的疑問是同樣的,那就進一步分析:
傳入值的各變量的初始狀態(地址狀態):
系統首先須要給字符串「alter」分配內存空間(地址),而後指針才指向其地址。
因此*str並無發生變化,所以最後打印出來的還是「this is a test」,這也解釋了我開始時的迷惑!
另外一種成功傳遞參數的指針調用方法----指針的指針:
- void my_malloc(void** p, int size)
- {
- *p = malloc(sizeof(int)*size);
- }
- int main()
- {
- int *a;
- my_malloc(&a , 10);
- return 1;
- }
執行結果:
![](http://static.javashuo.com/static/loading.gif)
(有些參數沒有用,只是爲了打印出來看看)
當咱們沒有執行到給*p分配空間的時候:
執行malloc(size) 後的圖以下:
賦值給*p後:因爲p指向&a即a的地址,*p則指向a的地址裏的值,如今又要把分配的內存指向*p,因此,a的值即爲新分配的內存!(這個比較難轉圈
![](http://static.javashuo.com/static/loading.gif)
)
而後,咱們就給指針a 分配內存成功了。
三、引用傳遞:
- void swapref(int &a,int &b)
- {
- cout << "******************before swapref:******************"<<endl;
- cout<<"a=" <<a<<" ,"<<"b="<<b<<endl;
- cout<<"&a=" <<&a<<" ,"<<"&b="<<&b<<endl;
- int temp;
- temp=a;
- a=b;
- b=temp;
- cout << "******************after swapref:******************"<<endl;
- cout<<"a=" <<a<<" ,"<<"b="<<b<<endl;
- cout<<"&a=" <<&a<<" ,"<<"&b="<<&b<<endl;
- }
- int main(){
- int x=1;
- int y=2;
- cout<<"******MAIN--BEFORE*****"<<endl;
- cout<<"x=" <<x<<" ,"<<"y="<<y<<endl;
- cout<<"&x=" <<&x<<" ,"<<"&y="<<&y<<endl;
-
- swapref(x, y);
- cout<<"*****MAIN--AFTER*****"<<endl;
- cout<<"x=" <<x<<" ,"<<"y="<<y<<endl;
- cout<<"&x=" <<&x<<" ,"<<"&y="<<&y<<endl;
- }
形如:int &a=x; //
用於引用傳遞,能夠理解爲a就是x,x就是a,只不過名字不同
執行結果:
這個具體就不分析了,記住引用傳遞實參和形參是同樣的,只是名字不一樣而已。
總結:
本文重點仍是在參數傳指針方面,指針確實使人頭疼,今天遇到了,會出錯,弄明白之後,等過段時間,又忘了,又遇到錯誤,再來看,這樣不斷反覆,但願能不斷的提高,對指針的認識不斷的加深!
寫了一下午,邊琢磨、邊參考、邊實驗,但願對你有用!錯誤之處敬請見諒!