複製鏈接
請複製以下鏈接發送給好友

引用參數

鎖定
引用參數是由調用部位傳入實參的地址(寫在留言板上)的形參
中文名
引用參數
用法種數
3
子程序
改變傳遞給引用參數
函數操縱
實參的本地拷貝

目錄

引用參數簡介

在形參表中以符號“&”開始的參數即為引用參數。如果一個形參是引用參數,調用部位將把實參的地址傳遞給子程序。子程序可以改變傳遞給引用參數的任何實參,因為子程序操作的是真正的變量,而不是它的副本。
把參數聲明成引用,實際上改變了缺省的按值傳遞參數的傳遞機制,在按值傳遞時,函數操縱的是實參的本地拷貝。

引用參數常見用法

一、引用參數的三種常見用法:
1.需要改變實參的值,比如swap()。參數是引用時,函數接收的是實參的左值而不是值的拷貝。這意味着函數知道實參在內存中的位置,因而能夠改變它的值或取它的地址。
2.向主調函數返回額外的結果。如下例:
1
/***Description: 測試引用傳遞的第二種使用方式* Author:charley* DateTime:2010-12-13 23:00* Compile Environment:win7 32 位 +vs2008***
/#include <iostream>
#include <vector>
using namespace std;
// 引用參數 'occurs' 可以含有第二個返回值
vector<int>::const_iterator look_up( const vector<int> &vec, int value, /* 值在 vector 中嗎?*/ int &occurs ) /* 多少次?*/
{
// res_iter 被初始化為最後一個元素的下一位置
vector<int>::const_iterator res_iter = vec.end();
occurs = 0;
for ( vector<int>::const_iterator iter = vec.begin(); iter != vec.end(); ++iter )
{
//判斷是否存在value
if ( *iter == value ) { //只有第一次找到value時,該項才成立;
//找到第二個value時res_iter已經被下一步賦值了,該項不成立
//達到在多次出現value的情況下,指向第一次出現的iterator 被返回
if ( res_iter == vec.end() )
res_iter = iter;
++occurs;
}
} //如果找不到該value值,返問一個指向vector 最後一個元素下一位置的iterator
return res_iter;
}
/*** 調用look_up方法*/
int main_test6()
{
vector<int> vInts;
int iVal;
cout<<"請輸入數字,按Ctrl+Z結束:"<<endl;
while(cin>>iVal)
vInts.push_back(iVal);
if(vInts.size()==0){
cout<<"沒有元素。"<<endl;
return -1;
}
cout<<"您輸入的結果如下:"<<endl;
for(vector<int>::const_iterator iter = vInts.begin(); iter!=vInts.end();iter++)
cout<<*iter<<"\t";
cout<<endl;
int occurs = 0; //查找該容器中是否含有值2。
vector<int>::const_iterator resIter = look_up(vInts,2,occurs);
if(!occurs)
{
cout<<"容器中不含2。"<<endl;
}
else {
cout<<"容器中2出現了:"<<occurs<<"次,*iterator為:"<<*resIter<<endl;
}
return 0;
}
3.向函數傳遞大型的類對象。例如:
class Huge {
public:
double stuff[1000];
};
extern int calc( const Huge & );
int main() {
Huge table[ 1000 ];
// ... 初始化 table
int sum = 0;
for ( int ix=0; ix < 1000; ++ix )
// 函數 calc() 將指向 Huge 類型的數組元素指定為實參
sum += calc( table[ix] );
// ...
}
二、如果引用參數不希望在被調用的函數內部被修改,那麼把參數聲明為 const 型的引用是個不錯的辦法。
如下例:
class X;
extern int foo_bar( X& );
int foo( const X& xx ) {
// 錯誤: const 傳遞給非 const
return foo_bar( xx );
}
為使該程序通過編譯 我們改變 foo_bar()的參數的類型 以下兩種聲明都是可以接受的
extern int foo_bar( const X& );
extern int foo_bar( X ); // 按值傳遞
或者可以傳遞一個 xx 的拷貝做實參 允許 foo_bar()改變它
int foo( const X &xx ) {
// ...
X x2 = xx; // 拷貝值
// 當 foo_bar() 改變它的引用參數時, x2 被改變, xx 保持不變
return foo_bar( x2 ); // ok
}
三、 我們可以聲明任意內置數據類型的引用參數
例如,如果程序員想修改指針本身,而不是指針引用的對象,那麼他可以聲明一個參數,該參數是一個指針的引用,例如:下面是交 換兩個指針的函數
?
12345
void ptrswap( int *&v1, int *&v2 ) { int *tmp = v2; v2 = v1; v1 = tmp; }
如下聲明
int *&v1; //實際是為指針取了一個別名,這樣就可以通過別名改變指針本身
應該從右向左讀,v1 是一個引用,它引用一個指針,指針指向 int 型的對象。
用函數 main() 操縱函數 rswap() 我們可以如下修改代碼以便交換兩個指針值:
1234567891011121314151617181920
#include <iostream> void ptrswap( int *&v1, int *&v2 ); int main() { int i = 10; int j = 20; int *pi = &i; int *pj = &j; cout << "Before ptrswap():\tpi: " << *pi << "\tpj: " << *pj << endl; //參數為指針的別名(即指針的引用,那麼傳遞的實參就是指針本身,道理和傳遞普通變量一樣的) ptrswap( pi, pj ); cout << "After ptrswap():\tpi: " << *pi << "\tpj: " << *pj << endl; return 0; }
編譯並運行程序 產生下列輸出
Before ptrswap(): pi: 10 pj: 20
After ptrswap(): pi: 20 pj: 10
四、引用參數還是指針參數
這2種參數都能夠改變實參的值,也可以有效的傳遞大型類對象,怎麼樣決定參數該聲明成哪種呢?
根本區別是:引用必須被初始化為指向一個對象,一旦初始化了,它就不能再指向其他對象;指針可以指向一系列不同的對象也可以什麼都不指向 。
因為指針可能指向一個對象或沒有任何對象,所以函數在確定指針實際指向一個有效的對象之前不能安全地解引用(dereference) 一個指針,例如:
class X;
void manip( X *px )
{
// 在解引用指針之前確信它非 0
if ( px != 0 )
// 解引用指針
}
另一方面,對於引用參數,函數不需要保證它指向一個對象。引用必須指向一個對象,甚至在我們不希望這樣時也是如此,例如 :
class Type { };
void operate( const Type& p1, const Type& p2 );
int main() {
Type obj1;
// 設置 obj1 為某個值
// 錯誤: 引用參數的實參不能為 0
Type obj2 = operate( obj1, 0 );
}
如果一個參數可能在函數中指向不同的對象,或者這個參數可能不指向任何對象,則必須使用指針參數 。
引用參數的一個重要用法是:它允許我們在有效地實現重載操作符的同時,還能保證用法的直觀性。
以Matrix 對象的加法重載操作符來舉例:
Matrix // 加法返回一個 Matrix 對象
operator+( // 重載操作符的名字
Matrix m1, // 操作符左操作數的類型
Matrix m2 // 操作符右操作數的類型
)
{
Matrix result;
// do the computation in result
return result;
}
可以這樣使用:
Matrix a,b,c; a = b+c; a+b+c;
但是operator+是按值傳遞,效率較低,如果我們改成指針參數:
Matrix operator+( Matrix *m1, Matrix *m2 )
{
Matrix result;
// 在 result 中計算
return result;
}
雖然在獲得了效率,但在使用時將出現這樣的代碼:a = &b +&c 和&( &a+&b)+&c;顯然並不友好。
下面是 Matrix類的重載加法操作符的修訂版本
// 使用引用參數的新實現
Matrix operator+( const Matrix &m1, const Matrix &m2 )
{
Matrix result;
// 在 result 中進行計算
return result;
}
該實現支持如下形式的 Matrix對象的加法
a + b + c