1. 程式人生 > >一個例子讓你理解c++的指標(傳遞動態記憶體)

一個例子讓你理解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;
}
所謂的引用傳遞就是指在呼叫函式的時候,將實參的地址傳遞到函式中,那麼在函式中對引數所進行的修改,將會影響到實際的引數.將一個變數引用傳遞給函式,這樣該函式就可以修改其引數(變數)的值。因為實參和形參引用了同一個地址,所以如果改變了形參的值,那麼實參的值也將會發生變化。