局部變量的返回

一般說來,函數中是可以進行局部變量的返回的,不然豈不是全部要用全局變量,如果使用了全局變量,那還有必要進行返回嗎?那函數就沒有它存在的意義了!但是要注意了,這裏所謂的局部變量的返回很有內涵,什麼樣的值纔可以進行返回而不出錯?


      其實,只要遵守一句話即可:函數不能返回指向棧內存的指針!


      爲什麼?因爲返回的都是值拷貝

      我們知道,局部變量的作用域是函數內部,函數一旦執行結束,棧上的局部變量會進行銷燬,內存得到釋放。因此,此時函數返回的是該局部變量的值拷貝,這是沒有問題的。但是如果返回的是局部變量的地址,那麼返回的只是該局部變量指針的拷貝,而隨着函數運行結束,該拷貝指針所指向的棧內存已經被釋放,那麼指向一個未知區域就會導致調用的錯誤。


      那如果返回的指針指向的是堆內存,又會怎麼樣?

      這樣的使用是沒有問題的,在函數內new空間,在函數外delete空間。但是這樣並不是一種好的編程風格,儘量在同一個作用域內進行new和delete操作,否則還要調用者手動進行內存的釋放,試問這樣的接口是不是很爛。如果確實需要這樣做,那就傳指針進去吧!


      好吧,通過幾個典型的例子看一下,返回局部變量要注意的地方。

      1.正確。最normal的情況。

  1. int returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<returnValue();  
  6.     return 0;  
  7. }  
  8.   
  9. char returnValue()  
  10. {  
  11.     int value=3;  
  12.     return value;  
  13. }  

      2.錯誤。最normal錯誤。雖然value被釋放,但是它的值不一定會被清除,所以有時候你這麼用看起來結果好像也是對的,但是隱患無窮。

  1. int* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<*(returnValue());  
  6.     return 0;  
  7. }  
  8.   
  9. int* returnValue()  
  10. {  
  11.     int value=3;  
  12.     return &value;  
  13. }  

      3.正確。不用奇怪,“HelloJacky”是一個字符串常量,儲存在只讀數據段,return str只是返回了該字符串在只讀數據段所在的首地址,當函數退出後,該字符串所在的內存不會被回收,所以是正常的。

  1. char* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<returnValue();  
  6.     return 0;  
  7. }  
  8.   
  9. char* returnValue()  
  10. {  
  11.     char* str="HelloJacky";  
  12.     return str;  
  13. }  

     4.錯誤。這一回“HelloJacky”是棧內的局部變量,函數退出時內存被釋放,因此返回棧內局部變量的地址是錯誤的。

  1. char* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<returnValue();  
  6.     return 0;  
  7. }  
  8.   
  9. char* returnValue()  
  10. {  
  11.     char str[]="HelloJacky";  
  12.     return str;  
  13. }  

      5.正確。如果你非要返回一個局部變量的地址,那麼加上static吧。

  1. char* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<returnValue();  
  6.     return 0;  
  7. }  
  8.   
  9. char* returnValue()  
  10. {  
  11.     static char str[]="HelloJacky";  
  12.     return str;  
  13. }  
      6.錯誤,一樣的,數組也不能作爲函數的返回值,因爲數組名其實是局部變量的首地址。

  1. int* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<*(returnValue());  
  6.     return 0;  
  7. }  
  8.   
  9. int* returnValue()  
  10. {  
  11.     int value[3]={1,2,3};  
  12.     return value;  
  13. }  
      7.正確。加上static修飾符吧,那數組也可以返回了。

  1. int* returnValue();  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     std::cout<<*(returnValue());  
  6.     return 0;  
  7. }  
  8.   
  9. int* returnValue()  
  10. {  
  11.     static int value[3]={1,2,3};  
  12.     return value;  
  13. }  

     8.正確。函數內申請空間,調用後釋放空間,只是這樣做的壞處就如上面所說接口不靈活。

  1. char* newMemory(int size);  
  2.   
  3. int _tmain(int argc, _TCHAR* argv[])  
  4. {  
  5.     char* p=newMemory(2);  
  6.     if(p!=NULL)  
  7.     {  
  8.         *p='a';  
  9.     }  
  10.     std::cout<<*p;  
  11.     delete [] p;  
  12.     return 0;  
  13. }  
  14.   
  15. char* newMemory(int size)  
  16. {  
  17.     char* p=NULL;  
  18.     p=new char[size];  
  19.     return p;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章