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