要以引用返回函數值,則函數定義時必須遵循以下格式: 類型標識符 &函數名 (形參列表及類型說明) { //函數體 } 可見,以引用返回函數值,定義函數時需要在函數名前加&。引用作為函數的返回值時,函數的返回值可以理解為函數返回了一個變量事實上,函數返回引用時,它返回的是一個指向返回值的隱式指針),因此,值為引用的函數可以用作賦值運算符的左操作數。另外,用引用返回一個函數值的最大好處是,在內存中不產生被返回值的副本。 #include<iostream> using namespace std; int &func() { static int num = 0; return ++num; } void main() { int i; for(i=0; i<5; i++) cout<<func()<<'\t'; cout<<endl; func()=10; for(i=0; i<5; i++) cout<<func()<<'\t'; cout<<endl; } 編譯並運行上述程序,其輸出結果如圖13.1所示,可見函數func被當作賦值運算符的左操作數來使用了。 圖13.1 程序輸出結果 下面再給出一個使用返回引用的函數作為左值的例子,它更有力地揭示了返回引用的函數的本質。 #include <iostream> using namespace std; double array[5] = {100.1, 100.2, 100.3, 100.4, 100.5}; double &change(int i) { return array[i]; } int main() { int i; cout<<"原始值如下: "; for(i = 0; i < 5; i++) cout << array[i] <<" "; cout<<endl; change(2) = 3.14; change(3) = -99.99; cout<<"修改後如下: "; for(i = 0; i < 5; i++) cout<<array[i]<<" "; cout<<endl; return 0; } 編譯並運行上述程序,其輸出結果請讀者自己實驗吧。函數change的返回值為double類型的引用,而該值又是一個由其參數i指定的數組array中元素的引用。因此,在主函數中,當語句“change(2) = 3.14;”被執行時,change函數返回的其實是對數組元素array[2]的引用。通過這個引用,array[2]被賦值3.14。隨後的語句“change(3) = -99.99;”同此原理。由於change返回的是數組中特定元素的引用,所以該函數可以放在賦值語句的左邊用來對這個數組元素進行賦值。注意前面講過沒有數組的引用,但是指向數組元素的引用時存在的。 在把引用作為返回值時有些一些地方需要提醒大家注意。 首先,不能返回局部變量或臨時變量的引用,但可以返回全局變量的引用,也就是說要注意被引用的對象不能超出作用域。主要原因是局部變量會在函數返回後被銷毀,因此被返回的引用就成為了“無所指”的引用,這是不被允許的。例如下面這段代碼就是錯誤的: int &func() { int i = 10; return i; } 在Visual C++ 6.0中,上述代碼在編譯時會拋出警告“warning C4172: returning address of local variable or temporary”,盡管編譯器沒有報錯,但這仍然意味著一種不安定。而且在Visual C++ 6.0中實驗上述func()函數作為左值來使用的情況,結果表明賦值並未成功,這同樣告誡我們這種用法是絕對應當被禁止的。畢竟,當函數func()返回時,局部變量i就超出了作用域。於是由func()返回的對i的引用就是未定義的引用。而且,某些對標准C++支持更強的編譯器中會對上述func()作左值的情況報錯!另外,這類問題也可能會間接產生,這時的錯誤顯得更加隱蔽而不容易被發現,所以當返回對一個對象的引用時,務必要仔細檢查這個對象是否會超出作用域。 其次,不能返回函數內部動態分配的內存的引用。雖然不存在局部變量的被動銷毀的問題,但是在此種情況下,仍然存在一些問題。例如,被函數返回的引用只是作為一個臨時變量出現,而沒有被賦予一個實際的變量,那麼這個引用所指向的由new分配的空間就無法被釋放,從而造成內存洩漏問題。 最後,可以返回類成員的引用,但最好是const常量。這是因為當對象的屬性是與某種業務規則相關聯的時候,其賦值常常與某些其它屬性或者對象的狀態有關,於是有必要將賦值操作封裝在一個業務規則當中。如果其它對象可以獲得該屬性的非常量引用,那麼對該屬性的單純賦值就會破壞業務規則的完整性。 --------------------------------------------------------------------
本文出自 “白馬負金羁” 博客,請務必保留此出處http://baimafujinji.blog.51cto.com/907111/195792