c++ 函数返回引用问题

源码如下:是在VS6上编译的。
#include <iostream>
using namespace std;

//int b=40; //当b为int和static int,f()=10后返回值不同
int &f()
{
int b=40;
return b;
}
//所谓返回引用是指返回一个已存在对象的引用,一定是已经存在的。返回值是一个引用。
int main()
{
int &e=f(); //此处是函数的执行,而非引用的引用。e是f()的别名,跟随f()变动
int e2=f(); //e2是引用函数的返回值,是一个引用。
cout<<"e's address = "<<&e<<"e's value="<<e<<endl;
cout<<"e2's address = "<<&e2<<"e2's value="<<e2<<endl;
cout<<"f()'s address = "<<&f()<<"f()'s value="<<f()<<endl;
f()=10;//此处是引用的指修改,即int b=5; int &a=b; a=6,此时a=6,b=6
cout<<"e's address = "<<&e<<"e's value="<<e<<endl;
cout<<"e2's address = "<<&e2<<"e2's value="<<e2<<endl;
cout<<"f()'s address = "<<&f()<<"f()'s value="<<f()<<endl;
return 0;
}

//b为auto类型,单步执行都是40,一次执行e第二次值为10,其余40
//b为static类型,单步执行为40,40,40,10,40,10,一次执行也是这样。

1、有人说引用绑定栈内存,引用绑定栈内存是什么意思?
2、为什么b为auto类型时,e单步执行和一次性执行结果不一样啊。主要是不明白怎么就产生这些值了。
3、为什么b为static类型时,e和f()的值为10,又是怎么回事,4、f()=10,这个到底是说函数的引用返回的值是10,或者就是简单赋值,赋值给谁呢?
还是说的什么呢,请多指教一下。非常感谢。

首先,永远不要返回局部变量的引用。因为局部变量在函数返回时被回收,即这个变量不存在了,所以以后对这个变量的引用都是无意义的,结果是不可预知的,程序很可能会崩溃。因此,也就不解释这种情形的结果了。

由于静态变量的声明周期直到程序结束,所以返回静态变量的引用是有意义的,而且安全的。下面解释返回静态变量的引用的情形:

#include <iostream>
using namespace std;

int& f(){
    static int b = 40;
    return b;
}

int main(){
    int& e = f();// e为b的别名
    int e2 = f();// e2为b的拷贝

    cout << "e's address = " << &e << "e's value=" << e << endl;
    cout << "e2's address = " << &e2 << "e2's value=" << e2 << endl;
    cout << "f()'s address = " << &f() << "f()'s value=" << f() << endl;
    // 因为e为b的别名,第一个和第三个输出一样

    f() = 10;// 修改b的值

    cout << "e's address = " << &e << "e's value=" << e << endl;
    cout << "e2's address = " << &e2 << "e2's value=" << e2 << endl;
    cout << "f()'s address = " << &f() << "f()'s value=" << f() << endl;
    // 因为e2为b的拷贝,不受影响

    return 0;
}

追问

请问f()=10为什么是修改b的值,f()我是把他理解为函数的返回值即return b语句吗?修改f()=10,等价于b=10吗?

追答

对的。

假设ff为f()的返回值,则ff的类型为int&,且ff = b,所以ff是b的别名。因为ff为f的返回值,所以f() = 10等价于ff = 10,故f() = 10等价于b = 10。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-06-18

    指的是你返回一个指向局部变量的引用,包括参数。

    b是int类型,auto在c++中是一个废弃的关键字,不过在c++11中被重新启用,用来自动推导类型。e是一个引用类型,即可以想象成就是被引用的对象,所以当你取e的地址时,其实获得的是被引用的对象地址。由于你的e引用的是一个局部变量,也就是栈上的变量,因为栈的起始地址一般都会随机变化,所以你会得到不一样的结果。随机变化的原因是为了防止某些类型的攻击,提高程序安全性。

    c++中不存在static类型一说,static是用来指示变量的生命周期类型,即静态生命周期。我想你是想说b是static int。当为static int时,程序启动时就会将b初始化为40,此时一直持续到程序结束,所以此时返回引用是合法,因为编译器保证,该变量生命周期会持续整个程序运行期间。

e2 = f();

这里返回引用,而e2不是引用,所以会进行拷贝初始化,所以e2和f()返回的引用是两个对象。e2为40。

f()=10;

这里由于返回引用,而引用指向static int b,所以会对b进行修改,于是b变为10。


e2是main的局部变量,e是引用,f()返回值是引用,此时e等价于f()。当取地址时,e2的地址将不会等于e的地址,因为他们是两个对象,两个对象的地址必然不同(除了一个类的子对象)。这里e2是局部变量,所以分配在栈上,而e,f()指向的是静态变量,所以分配在全局内存中。

追问

非常感谢你的回答,但只能采纳一个,楼上那位写个程序让我看明白了,因此采纳他的答案了,但你所补充的写的很好,非常感谢你。

追答

你可以顶一下你觉得有用的回答。

第2个回答  2014-06-18

    引用是绑定内存,意思是一个引用会锁定程序的地址空间中某一地址,地址是常量,只有该地址对应的内存单元的内容可以变化

    这个问题上,先说明一个原则:函数不要返回一个临时变量的引用。因为临时变量在栈区,函数结束时它的地址空间要回收再用,所以接下来这个地址的内容变成不可控。对于auto b的情况,就触犯了这个原则,没有研究的意义。至于为什么单步执行和一次执行结果不一样,可能是VC在不同的调试模式下对地址空间的使用不一样吧。

    b为static的时候,b处于程序的数据段,不在是栈区,因为b不是临时变量了,所以对b进行赋值后,它的状态会保留至函数结束。

    f()=10是赋值,b是auto时,赋值给栈内存;b是static时,赋值给数据段内存。

追问

非常感谢您的回答,言简意赅,切中要害,再加上你所说的和上面回答的,我总是弄明白了,但只能采纳一个答案,就给第一个了,但是非常感谢你。

相似回答