C++函数返回引用、非引用以及临时变量的问题

C++中新增了引用类型,所以函数的返回值可以是引用类型。那么就会有人想问 返回引用类型与返回非引用类型有区别吗?

结论是显然的,而且有明显的区别。尤其初学者会很容易绕进去。让我们先看四个函数原型。以int类型来举例

 (1) int fun(...)

         {

     return ....//后面跟的是一个引用

         }

例如:int fun(int &a)

        {

          return a; 

        }                                                                                        

  (2)int fun(...)

      {

      return....//后面跟的是一个非引用

       }

例如:int  fun(int a)

     {

     return a;

    }

 

  (3)int& fun(...)

      {

      return....//后面跟的是一个引用

       }

 (4)int& fun(...)

      {

 

      return....//后面跟的是一个非引用

 

       }

上面四种函数,(1)(2)是返回非引用类型的函数,(3)(4)是返回引用类型的函数。对于返回的是哪种类型的函数,我们要看函数名前面的参数类型,而不是函数体内return后的类型,这点切记!!!

一、C++规定当函数返回的是非引用类型时,函数会创建临时对象(temporary object),函数返回的就是这个临时对象。在求解表达式时,如果需要一个地方存储其运算结果,编译器会创建一个没有命名的对象,这就是临时对象。浅显的说,当你调用了函数,函数会 return一个值  那么这个值总得有存放的地方吧,编译器就把会把值存放在一个没有命名法临时对象中。

看一个简单的程序

对应于(2)
#include<iostream>
int fun(int &a)
{
int b=a;
return b;
}
int main()
{
 int a=8;
 int b=fun(a);//***
return 0;
}

int b=fun(a);分析此行代码:因为fun是返回非引用函数,调用fun函数,函数体内执行return时,需要创建临时变量temp,相当于执行了 int temp;然后把return的值赋值给temp,相当于执行了temp =b;然后用temp的值初始化b,相当于执行了int b=temp。

int b=fun(a);等加于int temp;temp=b;int b=temp;

当此表达式结束后 temp会消亡,所以不能int& b=fun(a); temp是在fun中的局部变量,fun调用完,表达式结束后,temp消亡,b引用的变量temp不存在了,所以编译不会通过。

 

对应于(1)

#include<iostream>
int fun(int &a)
{
return a;
}
int main()
{
 int a=8;
 int b=fun(a);//***
return 0;
}

int b=fun(a);分析此行代码:同上,等同于int temp;temp=a//用a引用的变量的值赋值给temp;int b=temp//用temp初始化b,当表达式结束后,temp会消亡。

二、C++规定当函数返回的是引用类型时。C++primer 上说当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身。

//find longer of two strings

const string &shorterString(const string &s1,const string &s2)

{

return s1.size()<s2.size()?s1:s2;

}//行参和返回类型都是指向const string对象的引用,调用函数和返回结果时,都没有复制这些string对象。

 

例如下面函数,请分析:

int a;

int& fun()

{

return a;

}//因为a是全局变量,函数的返回值是a本身,a具有全局作用域。假如a是函数内的局部变量,则函数会出错。

按照C++primer的说法 返回的是a这个全剧变量本身。为了跟返回非引用函数的统一,我本人理解返回的是对全局变量的引用即int b=fun(a);我理解为int &temp=a;int b=temp。可能这样理解有点牵强。函数返回的是引用,引用就是变量的别名,可以等同于初化它的对象,引用=变量(初始化引用的变量),所以函数返回的就算a变量本身。

 

 

int a;

 

int& fun()

 

{

 

 

int &b=a;

return b;

}//a的别名b,但是这个别名只能在fun函数体内使用,出了fun函数体就会消亡,函数返回值是引用,那么返回的其实就是a这个变量!!!

 

千万不要返回局部对象的引用

int &fun(int &a)

{

int b=a;

return b;

}

 

此函数运行会出错,因为它返回了局部对象的引用。当函数执行完毕,int b占用的存储空间会被释放,函数返回值指向了对于这个程序来说不再有效的内存空间。

确保返回引用安全的一个好方法是:请自问,这个引用指向哪个在此之前存在的对象?

 

三、把返回引用以及非引用的函数赋值给其他变量

函数返回值(int Func1())时,要产生一个临时变量作为函数返回值的副本(保存该函数调用中要返回的值),而用引用返回值 (int &Func2())时,不产生值的副本。故在用函数返回值定义一个引用(int &ia = Func1())时,该引用为临 时变量的引用,由于临时变量作用域短暂,故该引用存在随时无效的危险,是不合法的。而用引用返回值时,由于不产生值的副本,故 int &i = func2();在func2()的返回值是一个静态或者全局变量的情况下的调用是合法可行的,其直接用全局数据区中的变量来 初始化引用i,当然如果Func2中的返回值是局部变量,那么当然是非法的。

不妨自己再分析一下下面的四种函数调用:

条件:
int Func1();//假设是合法函数
int &Func2();//假设是合法函数

情况:
int &i = Func2();//引用i引用的是与一个变量,这个变量作用域大于等于int &i,合法
int &ia = Func1();//引用ia引用的是临时变量,不合法
int ib = Func1();//临时变量初始化ib,合法
int ic = Func2();//Func2返回的对象(变量)本身初始化ic;
记得这好像是钱能的那本C++教程里面的题目,应该没有记错。

总结:1.返回非引用类型函数的返回值为临时对象。此对象是return 所跟对象的拷贝。

(返回类型看函数名前面的类型,而不是return后面跟的)

            return 一个引用,那么就把引用的值赋给tem

            return一个变量(对象),那么就把变量的值赋给tem

            return 一个表达式,那么就把表达式的值赋给tem

 

           2.返回引用类型函数的返回值为return所跟对象的本身。

            return 一个引用,那么返回的就是引用所指的对象本身,因为引用是对象的别名,也就   是对象(变量)名。

            return 一个对象(变量),那么返回的就是对象本身。

 

posted @ 2014-09-18 22:49  coding_  阅读(3334)  评论(0编辑  收藏  举报