1. 程式人生 > >函式中區域性變數的返回

函式中區域性變數的返回

原文連結:http://blog.csdn.net/jackystudio/article/details/11523353

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

      其實,只要遵守一句話即可:函式不能返回指向棧記憶體的指標!

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

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

      那如果返回的指標指向的是堆記憶體,又會怎麼樣?

      這樣的使用是沒有問題的,在函式內new空間,在函式外delete空間。但是這樣並不是一種好的程式設計風格,儘量在同一個作用域內進行new和delete操作,否則還要呼叫者手動進行記憶體的釋放,試問這樣的介面是不是很爛。如果確實需要這樣做,那就傳指標進去吧!

      好吧,通過幾個典型的例子看一下,返回區域性變數要注意的地方。

      1.正確。最normal的情況。

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

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

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

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

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

     4.錯誤。這一回“HelloJacky”是棧內的區域性變數,函式退出時記憶體被釋放,因此返回棧內區域性變數的地址是錯誤的。

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

      5.正確。如果你非要返回一個區域性變數的地址,那麼加上static吧。

  1. char* returnValue();  
  2. int _tmain(int argc, _TCHAR* argv[])  
  3. {  
  4.     std::cout<<returnValue();  
  5.     return 0;  
  6. }  
  7. char* returnValue()  
  8. {  
  9.     staticchar str[]="HelloJacky";  
  10.     return str;  
  11. }  
      6.錯誤,一樣的,陣列也不能作為函式的返回值,因為陣列名其實是區域性變數的首地址。
  1. int* returnValue();  
  2. int _tmain(int argc, _TCHAR* argv[])  
  3. {  
  4.     std::cout<<*(returnValue());  
  5.     return 0;  
  6. }  
  7. int* returnValue()  
  8. {  
  9.     int value[3]={1,2,3};  
  10.     return value;  
  11. }  
      7.正確。加上static修飾符吧,那陣列也可以返回了。
  1. int* returnValue();  
  2. int _tmain(int argc, _TCHAR* argv[])  
  3. {  
  4.     std::cout<<*(returnValue());  
  5.     return 0;  
  6. }  
  7. int* returnValue()  
  8. {  
  9.     staticint value[3]={1,2,3};  
  10.     return value;  
  11. }  

     8.正確。函式內申請空間,呼叫後釋放空間,只是這樣做的壞處就如上面所說介面不靈活。

  1. char* newMemory(int size);  
  2. int _tmain(int argc, _TCHAR* argv[])  
  3. {  
  4.     char* p=newMemory(2);  
  5.     if(p!=NULL)  
  6.     {  
  7.         *p='a';  
  8.     }  
  9.     std::cout<<*p;  
  10.     delete [] p;  
  11.     return 0;  
  12. }  
  13. char* newMemory(int size)  
  14. {  
  15.     char* p=NULL;  
  16.     p=newchar[size];  
  17.     return p;  
  18. }