C++函數返回引用、非引用以及臨時變量的問題

C++中新增了引用類型,因此函數的返回值能夠是引用類型。那麼就會有人想問 返回引用類型與返回非引用類型有區別嗎?ios

結論是顯然的,並且有明顯的區別。尤爲初學者會很容易繞進去。讓咱們先看四個函數原型。以int類型來舉例安全

 (1) int fun(...)
函數

         {spa

     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後的類型,這點切記!!!

1、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會消亡。

2、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佔用的存儲空間會被釋放,函數返回值指向了對於這個程序來講再也不有效的內存空間。

確保返回引用安全的一個好方法是:請自問,這個引用指向哪一個在此以前存在的對象?

 

3、把返回引用以及非引用的函數賦值給其餘變量

函數返回值(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 一個對象(變量),那麼返回的就是對象自己。

相關文章
相關標籤/搜索