“引用作為函數參數”與 “引用作為函數返回值” 一、引用作為函數參數 作為函數參數時引用有兩種原因: 1、在函數內部會對此參數進行修改 2、提高函數調用和運行效率 關於第一點,都知道C++裡提到函數就會提到形參和實參。如果函數的參數實質就是形參,不過這個形參的作用域只是在函數體內部,也就是說實參和形參是兩個不同的東西,要想形參代替實參,肯定有一個值的傳遞。函數調用時,值的傳遞機制是通過“形參=實參”來對形參賦值達到傳值目的,產生了一個實參的副本。即使函數內部有對參數的修改,也只是針對形參,也就是那個副本,實參不會有任何更改。函數一旦結束,形參生命也宣告終結,做出的修改一樣沒對任何變量產生影響。 例如: void swap(int p1, int p2) //對兩個變量進行交換處理。此處函數的形參為p1, p2,沒有引用 { int p; p = p1; p1 = p2; p2 = p; } void main( ) { int a,b; cin >> a >> b; //輸入a,b兩變量的值 swap(a,b); //直接以變量a和b作為實參調用swap函數 cout << a << ' ' << b; //輸出結果 你會發現輸出的a和b還是你輸入的值,沒有交換。 如果我們改為: void swap(int &p1, int &p2) //對兩個變量進行交換處理。此處函數的形參為p1, p2都是引用 { int p; p = p1; p1 = p2; p2 = p; } 再次執行,就會發現值交換了。 原理就在於采用&p1和&p2時,p1和p2是實參的別名而已,像一個指針指向實參。改變p1和p2就是改變實參的值。 關於第二點,可以結合第一點分析,p1和p2是實參的引用,不用經過值的傳遞機制,已經有了實參值的信息。所以沒有了傳值和生成副本的時間和空間消耗。當程序對效率要求比較高時,這是非常必要的. 二、引用作為函數返回值 說明: (1)以引用返回函數值,定義函數時需要在函數名前加& (2)用引用返回一個函數值的最大好處是,在內存中不產生被返回值的副本。 例如: #include <iostream.h> float temp; //定義全局變量temp float fn1(float r); //聲明函數fn1 float &fn2(float r); //聲明函數fn2 float fn1(float r) //定義函數fn1,它以返回值的方法返回函數值 { temp=(float)(r*r*3.14); return temp; } float &fn2(float r) //定義函數fn2,它以引用方式返回函數值 { temp=(float)(r*r*3.14); return temp; } void main() //主函數 { float a=fn1(10.0); //第1種情況,系統生成要返回值的副本(即臨時變量) float &b=fn1(10.0); //第2種情況,可能會出錯(不同 C++系統有不同規定) //不能從被調函數中返回一個臨時變量或局部變量的引用 float c=fn2(10.0); //第3種情況,系統不生成返回值的副本 //可以從被調函數中返回一個全局變量的引用 float &d=fn2(10.0); //第4種情況,系統不生成返回值的副本 //可以從被調函數中返回一個全局變量的引用 cout<<a<<c<<d; } 引用作為返回值,必須遵守以下規則: (1)不能返回局部變量的引用。主要原因是局部變量會在函數返回後被銷毀,因此被返回的引用就成為了"無所指"的引用,程序會進入未知狀態。 (2)不能返回函數內部new分配的內存的引用。雖然不存在局部變量的被動銷毀問題,可對於這種情況(返回函數內部new分配內存的引用),又面臨其它尴尬局面。例如,被函數返回的引用只是作為一 個臨時變量出現,而沒有被賦予一個實際的變量,那麼這個引用所指向的空間(由new分配)就無法釋放,造成memory leak。 (3)可以返回類成員的引用,但最好是const。主要原因是當對象的屬性是與某種業務規則(business rule)相關聯的時候,其賦值常常與某些其它屬性或者對象的狀態有關,因此有必要將賦值操作封裝在一個業務規則當中。如果其它對象可以獲得該屬性的非常 量引用(或指針),那麼對該屬性的單純賦值就會破壞業務規則的完整性。