C++为什么中不应该返回局部变量的地址

在这里插入图片描述
最近在写代码的时候遇到返回局部变量的引用问题,认识不是很清晰,下面是转自http://blog.csdn.net/tujinqiuqq85948239/article/details/27236677博文的详细解释!
在Effective C++中明确指出:不应该返回局部变量的引用,原因在于:局部变量会在函数返回后被销毁,因此被返回的引用就成为了”无所指”的引用,程序会进入未知状态。如果比较理解函数局部变量的作用域和生命周期,那么这一点很好理解。
在C++中,实际上引用和指针类似,都是变量的实际存储地址。既然不能返回局部变量的引用,
如下所示,这样做是不合理的:
int &getRefer()
{

     int pp = 8;
     return pp;

}
所以,返回局部变量的地址作为指针也是不合理的:
int *getPoint()
{

     int pp = 8;
     return &pp;

}
返回的地址指向一个过期的对象,后面可能发生不可预知的行为。
int &getRefer()
{

	 int pp = 8;
	 return pp; 

}
int main()
{

	 int &ppp = getRefer();
	 ppp = ppp + 3;
	 return 0;

}
你会发现,编译器会警告:试图返回局部变量的地址,但是还是可以编译通过。运行的时候,int &ppp = getRefer()语句之后,ppp确实等于8,ppp = ppp + 3之后,ppp确实等于11,奇怪了,当时我就想难道这个局部变量起死回生了???怎么还能这么正常的使用???那为什么编译器又会警告了呢?我查了好多资料,才发现这和函数调用时栈指针的处理方式有关:
当你调用getRefer函数时,函数栈指针会根据函数里面的局部变量的内存分配(编译器自动分配)而依次向后移动,当函数调用完毕,栈指针回撤,回撤到外部调用函数的地方,这个时候,函数局部变量,比如这里的pp使用的内存已经被收回(pp的生命周期已经结束),但是这个内存里面的内容还是8,所以ppp确实指向这块内存,而且内存存储的内容没有发生改变。所以造成一种假象,就是我们以为局部变量的生命周期延长了。

这快内存我们可以使用诸如上面所示的ppp = ppp + 3来修改内容,但是这块内存的所有权并不在我们手里,而是在系统手里,系统随时有可能改变这块内存中的内容。所以我们说后面的结果是不可预知的。下面我来说明如何演示系统会改变这块内存的内容:
int &getRefer()
{

 int pp = 8;
 return pp;

}

int shiyi()
{

	int temp1 = 100;
	int temp2 = 200;
	return temp1 + temp2;

}

int main()
{

    int &ppp = getRefer();
    int temp = shiyi();
    ppp = ppp + 3;
    return 0;

}
这里与前面的区别仅仅在于在getRefer函数调用之后,又调用了一个与它完全不相关的函数shiyi。
我们在getRefer函数调用之后,发现ppp = 8,这是因为系统还没有覆盖使用这块内存,然后我们调用shiyi函数,如前面所述,函数内部会给局部变量分配栈内存,函数栈指针后移,这个时候,系统很有可能就使用了前面ppp = 8的这块内存,这里在调用shiyi之后,你会发现ppp的值也跟着变成了200!!!这是因为编译器在调用shiyi函数的时候将ppp指向的内存由8改成了200!!!这就是前面所说的不可预料的结果,因为你不能知道这个ppp会怎么变化,它完全不受控制,调用任何一个函数或者其他行为都有可能覆盖这块内存。
所以不要试图返回一个局部变量的引用,也不要试图返回一个指向局部变量的指针,用一句话说就是不要返回一个局部变量的地址。

下面是我自己随便写的一个列子 自己可以试一下打印的结果

using namespace std;

int &fun(int a)
{
return a;
}
int main()
{

int &b = fun(10);
printf("%d\n",b);  //这个时候b指向的内存空间还没有被修改,但是控制权不在自己手上,而是在操作系统的手上 
 不知道什么时候会被修改或者使用  当执行了下一句或者某个行为之后 这段内存就可能被修改了,从而指向的地方是未知的 
printf("%d\n",20);
printf("%d\n",b);//所以这里输出的是一个随机值
return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值