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;
 }

返回的地址指向一个过期的对象,后面可能发生不可预知的行为。

但是当我在VC中写下如下代码:

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函数时,函数栈指针会根据函数里面的局部变量的内存分配(编译器自动分配)而依次向后移动,当函数调用完毕,栈指针回撤,回撤到外部调用函数的地方,这个时候,函数局部变量,比如这里的ppp使用的内存已经被收回(ppp的生命周期已经结束),但是这个内存里面的内容还是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会怎么变化,它完全不受控制,调用任何一个函数或者其他行为都有可能覆盖这块内存。

所以不要试图返回一个局部变量的引用,也不要试图返回一个指向局部变量的指针,用一句话说就是不要返回一个局部变量的地址。

猜你喜欢

转载自blog.csdn.net/weixin_37818081/article/details/78627588
今日推荐