1、函数返回指针
以下例子中,返回的指针指向的是一个局部变量 a 的地址,当 funcInt 函数结束时,a 的生命周期也就结束了,a 所占用的内存空间将被释放,此时指针指向的地址不变,但是存储值是一个未知数,再使用这个指针是未定义的行为,可能会导致程序崩溃或者出现其他异常。
#include "iostream"
// 返回int指针地址
int * funcInt(){
int a = 101;
return &a;
}
int main() {
int *pInt = funcInt();
std::cout <<"funcInt:" <<*pInt<< std::endl;
return 0;
}
打印结果:
funcInt:32760
通过结果可以看出,结果并不是我们期待的值 101
,所以代码这么写是有问题的,也是不安全的行为;
解决方案一:使用 static
使用static 表示将这个变量存储到全局区(static静态区),此时就不受栈区管控,当funcInt 函数执行完成后,数据依然存在,代码如下:
#include "iostream"
// 返回int指针地址
int * funcInt(){
static int a = 101;
return &a;
}
int main() {
int *pInt = funcInt();
std::cout <<"funcInt:" <<*pInt<< std::endl;
return 0;
}
解决方案一:使用 动态分配内存 new
动态分配的内存空间,手动释放后才会清除数据,代码如下
// 返回动态分配内存的int指针
int * funcIntNew(){
int * a = new int(101);
// 动态分配的内存空间,手动释放后才会清除数据
return a;
}
int main() {
int *aNew = funcIntNew();
std::cout <<"aNew:" <<*aNew<< std::endl;
delete aNew;//动态分配的内存必须手动释放
}
2、函数返回引用
引用和指针是一样的,因为引用其实就是带const的指针,
int & funcInt(){
int a= 100;
int & a_ref = a;
return a_ref;
}
int main() {
int &i= funcInt();
std::cout <<"funcInt:" <<i<< std::endl;
}
打印结果:
funcInt:32760
可以发现,打印的也是不确定的值;并不是我们期待的100
,这是因为 返回的指针指向的是一个局部变量 a 的地址,当 funcInt 函数结束时,a 的生命周期也就结束了,a 所占用的内存空间将被释放,再使用这个指针是未定义的行为,可能会导致程序崩溃或者出现其他异常。
解决方案一:static
// 返回静态变量的引用(安全)
int & funcIntStatic(){
static int a= 100;
int & a_ref = a;
return a_ref;
}
int main() {
int &i1= funcIntStatic();
std::cout <<"funcIntStatic:" <<i1<< std::endl; // 打印结果:funcIntStatic:100
}
错误示范:使用动态分配内存new
// 返回动态分配内存变量的引用(不安全,未释放动态分配的内存空间)
int & funcIntNew(){
int *a= new int(100);
int & a_ref = *a;
//delete a; // 一旦释放,main 函数中获取到的值就不确定了,
return a_ref;
}
int main() {
int &i2= funcIntNew();
std::cout <<"funcIntNew:" <<i2<< std::endl;
}