这里记录一下C++关于不能返回局部变量的指针的研究。关于C++不能返回局部变量的引用很好理解,这里就不探讨了。以下如有不对的,麻烦纠正一下,一起学习进步~。
先总结一下吧:
C++Primer中这句话的含义我认为是我不要使用任何在栈内存中分配内存的变量的引用或者指针作为返回值,由于栈内存在方法执行完毕后会将栈内存释放,因此得到的返回值是指向的地址是无效的。
在Java中我们可以随意的返回一个对象,如下:
//常量
public String getTest(){
String result="sadads";
return result;
}
//对象
public Test get(){
Test test=new Test();
return test;
}
我的理解是由于对象分配的内存在堆上,而常量则记录在方法区(上述的例子的"sadads"),而不是在虚拟栈中进行的内存分配,随着一个方法的结束,虽然栈帧中的内存释放了,但是对象在GC回收之前仍然在堆中存活,更别说常量了。
而对于C++而言,局部变量可能有很多种,包括数组,基本变量,以及我们自己写的对象,一一看下对应的返回局部变量指针的正确性。
返回数组局部变量的指针
首先我们看下数组的形式:
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
对于基本变量而言,由于常量都声明在常量区,在方法执行完毕后并不会随着栈内存的消除而销毁,所以返回对应指针是可行的。
####返回对象的局部变量指针
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++后才能解答,学习初期先放在着,待日后了解后解答。