這裏記錄一下C++關於不能返回局部變量的指針的研究。關於C++不能返回局部變量的引用很好理解,這裏就不探討了。如下若有不對的,麻煩糾正一下,一塊兒學習進步~。java
先總結一下吧:c++
C++Primer中這句話的含義我認爲是我不要使用任何在棧內存中分配內存的變量的引用或者指針做爲返回值,因爲棧內存在方法執行完畢後會將棧內存釋放,所以獲得的返回值是指向的地址是無效的。數組
在Java中咱們能夠隨意的返回一個對象,以下:學習
//常量 public String getTest(){ String result="sadads"; return result; } //對象 public Test get(){ Test test=new Test(); return test; }
個人理解是因爲對象分配的內存在堆上,而常量則記錄在方法區(上述的例子的"sadads"),而不是在虛擬棧中進行的內存分配,隨着一個方法的結束,雖然棧幀中的內存釋放了,可是對象在GC回收以前仍然在堆中存活,更別說常量了。測試
而對於C++而言,局部變量可能有不少種,包括數組,基本變量,以及咱們本身寫的對象,一一看下對應的返回局部變量指針的正確性。指針
首先咱們看下數組的形式:code
char* ee(){ char x[]="12323"; char*p=x; return p; } int main(int argc, const char * argv[]) { std::cout<<"----"<<*ee()<<std::endl; return 0; } //返回結果:----1
從上面結果能夠看出結果是不對的,這是因爲數組分配的內存存在於棧內存當中,x的生命結束,其所佔內存被釋放,p也被釋放,返回回來的是被釋放的內存,輸出必然不正確。那若是咱們須要他返回正確的值,須要如何修改呢?其實也簡單,主要是使用堆內存來消除棧內存的約束,或者使用實參方式記錄地址,這裏直接使用堆內存來距離:對象
char* ee(){ char* xx=new char[3]{'k','b'}; char*p=xx; return p; } int main(int argc, const char * argv[]) { std::cout<<"----"<<*ee()<<std::endl; return 0; } //輸出結果:----k
這樣就是正確的了。內存
const char* getChar(){ const char *p="2234"; return p; } int* getInt(){ int x=12; int* p=&x; return p; } int main(int argc, const char * argv[]) { std::cout<<*getInt()<<"----"<<*getChar()<<std::endl; return 0; } //返回結果:12----2
對於基本變量而言,因爲常量都聲明在常量區,在方法執行完畢後並不會隨着棧內存的消除而銷燬,因此返回對應指針是可行的。get
####返回對象的局部變量指針
std::string* geTest(){ std::string test="123"; std::string *p=&test; return p; }; //返回結果:沒法識別
這裏使用string對象當作測試的例子,獲得了無效的結果,推測string對象在棧內存中進行了分配內存的操做,致使了對應的結果,再在堆上進行測試:
std::string* getTestV2(){ std::string* str=new std::string("123"); return str; } int main(int argc, const char * argv[]) { int k=12; std::cout<<*getTestV2()<<std::endl; return 0; } //輸出結果爲123
經過上述的方式,咱們就能夠獲得先前在文章前頭的總結,可是這裏有個疑問,當我寫以下代碼的時候:
const char* getChar(){ std::string str="2234"; const char *p=str.c_str(); return p; }
發現能返回正確的結果,這個就有點懵逼了,先留在文章這裏吧,這種問題仍是須要深刻理解C++後才能解答,學習初期先放在着,待往後瞭解後解答。