一個例子讓你理解c++的指標(傳遞動態記憶體)
經常搞不懂C/C++的指標,但是指標是C系語言的特點,也是它的精華所在,指標即一個數據物件的記憶體地址。指標問題,包括常量指標、陣列指標、函式指標、this指標、指標傳值、指向指標的指標等都是各大公司的常備考點。下面我們就來看看一個例子,好好理解理解指標吧
#include <iostream> using namespace std; void swap1(int p,int q){ int temp; temp = p; p = q ; q = temp; } void swap2(int *p,int*q){ int *temp; *temp = *p; *p = * q; *q = *temp; } void swap3(int *p,int *q){ int *temp; temp = p ; p = q; q = temp; } void swap4(int *p,int *q){ int temp; temp = *p; *p = *q; *q = temp; } void swap5(int &p,int &q){ int temp; temp = p; p = q; q = temp; } int main(){ int a,b; swap1(a,b); //swap2(&a,&b); //swap3(&a,&b); //swap4(&a,&b); //swap5(a,b); cout<<a<<" "<<"b"<<endl; return 0; }
這個例子包含了函式引數傳遞、值傳遞、指標傳遞(地址傳遞)、引用傳遞的知識點
分別執行swap1(a,b)、swap2(a,b)、swap3(a,b)、swap4(a,b)、swap5(a,b);
他們會有何不同的結果
1.對於sawp1(a,b)來說,p和q就是形參,a,b是實參,swap1傳的是值得副本,只是在函式體內修改了形參p,q的值,p和q的值確實是交換了,但是他們只是區域性變數,並不會影響到主函式的a和b;當函式生命週期結束時,p和q所在的棧也就被刪除了
2.swap2(&a,&b)傳的是一個地址進去,在函式體內的形參*p和*q是指向了實際引數a,b的記憶體地址的
but!!!
要注意!
int *temp;
*temp = *p;
這段程式碼的意思是:我新建了一個指標*temp;但是並沒有給他分配記憶體,所以
*temp = *p是賦值而並非指向!要注意理解,就是將指標p所指向的記憶體裡的值賦值到指標temp所指向的記憶體裡的值。但是不是沒有給*temp分配記憶體嗎?所以,系統就在賦值的時候臨時的給*temp隨機的地址,讓它存值。分配的隨機地址是個“意外”,並且函式結束後還不收回!!這樣就會造成記憶體洩漏!!如下圖
那麼到底這段程式碼能否實現資料交換?其實還得看編譯器,像vs2008這樣嚴格一點的編譯器,是會報錯的
3.swap3(a,b)傳的是一個地址過去,與swap2不同的是
*temp = * p ;//swap2 賦值
temp = p; //swap3 指向
/*swap2和swap3同樣都沒給temp指標分配記憶體
*不同的是以上這兩段程式碼。temp=p是指向,而不是複製了,temp是指向了p指標所指向的地址,也就是a
*/
而程式碼
p = q;
q = temp;
/*其意思就是指標p指向了指標q所指向的地址,q又指向了指標temp所指向的地址,其實和temp=p是一個意思;
如下圖所示
*/
所以swap3只是改變了指標的指向,並沒有改變a,b的值。
舉一個很形象的例子。假設有a,b兩個倉庫,p和q分別是它們的備用鑰匙(注意是備用!),現在我們進入了函式體swap3(), 使得p,q鑰匙的功能改變了,p用來開啟b倉庫,q用來開啟a倉庫,但是a倉庫本身的貨物並沒有發生什麼變化,裡面存放的是大米現在也依然是大米,b倉庫原來放的是辣椒那現在也還是辣椒。函式結束,兩把備用的“鑰匙”就會自動銷燬,而主函式裡用主鑰匙開啟a,b倉庫,發現值還是沒變化。
4.swap4,修改了指標所指向的地址中的值
int *temp;
temp = *p;
*p = q;
*q = temp;
將指標p所指向的地址的值賦值給temp指標所指向的地址,*p=q,就是q指標所指向的地址賦值給指標p所指向的地址中的值,所以指標p所指向的a(地址)中的值就變成了b(b是q指標所指向的地址),同理指標temp所指向的地址就賦值給了q指標所指向的地址中的值,也就是說將最初p指標所指向的地址的值賦值給了q指標所指向的地址的值。沒毛病,其實交換的本質就是這樣的:最初的p的值要換成q的值,而q的值要換成最初p的值,所以只是將最初p的值給臨時儲存下來。
5.swap5和swap4是類似的。是一個引用傳遞,修改的結果直接影響實參。
void swap5(int &p,int &q){
int temp = p;
p = q;
q = temp;
}
所謂的引用傳遞就是指在呼叫函式的時候,將實參的地址傳遞到函式中,那麼在函式中對引數所進行的修改,將會影響到實際的引數.將一個變數引用傳遞給函式,這樣該函式就可以修改其引數(變數)的值。因為實參和形參引用了同一個地址,所以如果改變了形參的值,那麼實參的值也將會發生變化。