为什么不能从子函数中返回临时对象的指针和引用,却可以返回一个临时变量的值

参考文章链接:
http://blog.csdn.net/hlsdbd1990/article/details/45970959
http://blog.csdn.net/misskissc/article/details/10757975
http://bbs.csdn.net/topics/390153974
http://bbs.csdn.net/topics/90228917
感谢两位博主和讨论区中的各位大神,答疑解惑。

最近在看c++的文章的时候,经常看到不能返回局部对象的引用和指针,因为临时对象是分配在栈内存中的,栈内存是由系统自动进行管理和释放的,用户无权进行管理。而堆内存可以由用户自定义分配,可以采用new、delete 运算符、malloc、free 函数进行。
看到这句话的时候,一直有个问题没有理解,为什么函数却可以返回一个局部变量的值呢?就是在初学c语言的时候,经常可以看到下面这种写法。

     int temp_f(void)
{
    int a = 10;
    return a;
}
int main()
{
    int b;
    b = temp_f();
    cout << "b= " << b << endl;
    return 0;
}

后来看到文章中第二个链接中博主写的博客,才突然理解了这句话。借用下博主的话:
分析子函数调用的过程
【1】当程序执行到第4行调用子函数temp_f,程序转到到temp_f子函数入口地址处。
【2】程序进入temp_f子函数(即此子函数开始运行 ),执行到”return a;”时,系统将返回的 a的值 ,存入 寄存器eax中,然后经‘}’标志后函数运行完毕。若子函数中有形参和局部变量,则在函数开始运行时,系统自动为局部变量分配栈空间,待函数运行完毕时系统自动释放在栈中为局部变量分配的内存单元中的数据。
【3】temp_f 子函数执行完毕,函数返回到调用子函数的地方即第4行处继续执行,将保存在寄存器eax中的值即 10(是一个具体的值,而不是变量的地址,临时变量的那段内存是已经释放了,但是临时变量的值已经拷贝出来了) 赋给变量b。

关键的问题在于第二句中,若子函数中有形参和局部变量,则在函数开始运行时,系统自动为局部变量分配栈空间,待函数运行完毕时系统自动释放在栈中为局部变量分配的内存单元中的数据。解释一下就是,如果子函数中如果有局部变量为指针、或者返回一个变量的引用时,虽然是系统也会把返回值存入到寄存器中,但是请注意此时存入的值是一个“系统临时在栈内存中给临时变量分配的内存地址”,虽然说在调用过程中,把该地址赋给了函数调用处的变量,但是给地址,在子函数结束之后就已经释放了,里面的内容是一个随机值。因此说不能在子函数中返回局部对象的引用和指针。

int temp_f(void)
{
    int a = 10;
    return a;
}
int* temp_p(void)
{
    int a = 100;
    int *p = &a;
    cout << "temp_p= " << p << endl;
    return p;
}
int & temp_r(void)
{
    int a = 1000;
    cout << "&a=" << &a << endl;
    return a;
}
int main()
{
    int b=1;
    b = temp_f();
    cout << "b= " << b << endl;

    int *main_p = NULL;
    main_p = temp_p();
    cout << "main_p= " << main_p << endl;
    cout << "*main_p= " << *main_p << endl;

    int main_r = temp_r();
    cout << "main_r=  " << main_r << endl;

    system("pause");
    return 0;
}

输出的结果:

b= 10
temp_p= 00D9F7BC
main_p= 00D9F7BC
*main_p= 252756400
&a=00D9F7BC
main_r=  1000
请按任意键继续. . .

但是有的时候,我们会发现,你即使是返回变量的引用,你在调用函数的时候,也会发现可以返回正确值,比如说上面的这个程序中的 temp_r函数,在main函数中调用的时候,也能返回正确的值。这个并推翻上面的结论,只能说明你的程序太小了。因为原来储存 局部变量 的那段地址空间还没有被别的代码应用,里面存储的值还没有被覆盖,所以才会得到正确的结果。 如果折这段地址空间被分配给别的代码使用,那么就会出现错误了。
从上面的代码测试结果中也是可以发现的,就是如果子函数返回一个指针的话,在主函数中调用的时候,你会发现返回值和返回临时变量的地址是一样的,但是存放的内容变成了一个随机值。

你可能感兴趣的:(C++)