C++指針、引用知多少?


 

     上午搞了一個小程序,test半天都沒有得到想要的結構,原來是遞歸的時候沒有注意的循環的問題,結果直接死循環了。催了...看來當程序出現問題的時候,首先要整理的是算法思路是否有問題,其次是算法的實現,是否容易進入死循環,邊界條件是否出現錯誤。

       好的,廢話不多說,繼續整理。

       指針

       指針這東西,要是搞復雜了,這還真是高深莫測,你不認真研讀研讀還真不行,真心覺得搞程序一浮躁,各種bug就都出來了。

       指針的聲明:

1     int x=20; 2     int *p,q; 3     int* m,n; 4     p=&x; 5     q=x; 6     m=&x; 7     n=x; 8     cout<<*p<<" "<<q<<" "<<*m<<" "<<n;

     我想,這應該就是最簡單的聲明了吧,p是一個指針,並且是一個指向x的指針。那么如果cout<<p;會得到什么結構呢?其實p本身保存的是一個地址。並且保存的是x所存儲的地址。

   不信的話可以改成以下語句:

1     int x=20; 2     int *p,q; 3     int* m,n; 4     p=&x; 5     q=x; 6     m=&x; 7     n=x; 8     cout<<p<<" "<<&x<<" "<<m;

   他的輸出結果就是:

  

   所以,在這里我們已經對指針有一個初步的認識,指針其實就是一個地址的東西,只不過這個地址保存的是我們所指向的值得地址。

   空指針void*

   我們一般的指明了指向類型的指針都是只能指向該類型的,比如說上面提到的p指針,它只能指向Int類型。但是void*是怎么樣的呢?

   其實void*指針可以指向任何類型,當然也可以指向int。如果我們下面代碼會出現什么情況呢?

1     void *y; 2     y=&x; 3     cout<<y;

   實際上我們會發現,y輸出的是地址,並且和上面的P,m的地址是一致的,實驗發現,我上面的說法是對的。

   很顯然,如果僅僅得到一個void*指針是沒有太大意義的,那么我們怎么把他轉化成原有的int*,甚至轉化成int呢?

   這里我們需要顯示轉化,(int*)y,轉化成整數的話就是*((int*)y);

   所以現在我們應該知道了當函數的返回值是void和void*是有多么大的不同了吧。void*是返回一個特殊的指針類型。

   多重指針

   這里說的多重指針在很多地方也稱為指向指針的指針。

   我們是不是經常會遇到int **m;這種情況呢,其實他就是一個多重指針。

   還是上面那個例子,我們以下定義一個多重指針

1     int **z; 2     z=&p; 3     cout<<"多重指針"<<p<<*z;

   p我們知道會輸出x的地址,那么*z又是上面呢,z是一個指向指針p的指針。那么z保存的是p的地址,*z理所當然的應該保存的也是x的地址。見下圖

   了解了這個之后,那么我們就很容易的知道了,動態二維數組的創建過程了,就是一個指向指針的指針,二重指針嘛,so easy。

   函數指針

   我們經常會需要動態的調動幾個函數的某一個,如果我們只是if else那代碼量可能有時候會比較大,有沒有可以在函數參數中直接傳遞一個函數呢?

   答案是不可能的,但是我們有一種方式可以實現,那就是通過指針函數來說。

   typedef void (*pf)(int &m,int *n);

   這是什么意思呢?他的意思就是說pf是一個指針函數,他可以指向任意的返回值為void,並且參數是int &m和int *n的函數。

    同樣我們聲明pf f;就可以把f作為一個函數了,也可以把f當做一個參數傳到函數體中了。具體例子見下面。

 1 void swap(int &m,int *n); //定義一個有兩個參數的函數swap
 2 typedef void (*pf)(int &m,int *n);//  3 void print(int &m,int *n,pf x);//定義一個能傳遞指針函數的函數
 4 int _tmain(int argc, _TCHAR* argv[])  5 {  6     int m=6,q=20;  7     pf f=swap;  8     int* n=&q;  9  f(m,n); 10     cout<<&m<<*n; 11  print(m,n,f); 12     system("pause"); 13     return 0; 14 }

    同樣的道理,我們也可以返回一個指針函數,只不過返回類型是pf。它返回的實際類型應該是 void (*)(int&,int*);解釋起來就是一個指向兩個傳輸的函數指針。

   我們可以定義一個 pf fun();他就返回的是函數指針了。

    引用&

    實際上引用能起到的作用,*很多時候也能夠起到,那為什么我們還經常說,要盡量使用引用呢?最大的優點就是指針更安全。當然某些情況下例外。

    引用可以認為是一個別名,而指針則是一個實體,雖然他們都有地址的概念在里面。

    這里主要描述一下引用和指針的不同之處。

     1、指針是可以重新指向另外一個對象,而引用不行,引用一旦綁定那就不能再綁定其他了,引用的這種性質有一點嫁雞隨雞嫁狗隨狗的意味在里面。這對男人是不是更安全呢?O(∩_∩)O哈哈~

     2、指針可以是空指針,但是引用不能是空引用啊,所以引用都是必須初始化的。

     3、指針是指向一個實體(程序為指針變量分配內存區域),而指針則是一個別名,這個可以怎么理解呢?我們通過sizeof(指針)和sizeof(引用)可以知道,前者是指針的大小,一般為4,而后者則是引用對象的大小,也就是說,如果對一個字符串長度為100的字符串進行引用sizeof是100哦,而指針還是4.

    4、如果需要返回動態分配的對象或者內存,應該使用指針,引用很有可能引起內存泄露問題。

    當然還有其他的一些不同,但是總體來說都是由以上衍生出來的。

    其實引用本質上來說是一種指針,只不過編譯器進行了優化(所以指針更加靈活),所以引用具有指針的特點,又更安全。

 

 

     版權所有,歡迎轉載,但是轉載請注明出處:瀟一

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM