C++中傳值引數和引用引數和指標怎樣區別?
C++中傳值引數和引用引數怎樣區別呢?
看以下例子:
#include<iostream>
using namespace std;
void swap(int a,int b)
{
int temp;
temp=a;
a=b;
b=temp;
}
main()
{
int a=3,b=5;
cout<< "before ‘swap’:a="<<a<<",b="<<b<<endl;
swap(a,b);
cout<<"after ‘swap’:a="<<a<<",b="<<b<<endl;
}
這個例子是傳值呼叫, 意思就是 形參 的 改變不會影響 實參的值。
你執行一下可知 主函式呼叫了swap函式後 a,b的值並沒有發生交換。
原因是,呼叫swap函式時 編譯器為 swap(int a,int b) 中的形參 a , b單獨分配記憶體空間,並接受主函式傳遞來的值,這塊記憶體空間和 main()函式中的 a ,b 不是同一記憶體空間。 所以在swap(int a,int b) 中 a , b發生了交換,但main函式中a , b沒發生交換。即主調函式與被調函式的操作物件各不相同,引數僅在呼叫時由實參向形參傳遞,而不可由形參向實參傳遞。
要使a ,b發生交換 需要使用傳址呼叫。程式改為如下:
#include<iostream>
using namespace std;
void swap(int &
{
int temp;
temp=a;
a=b;
b=temp;
cout<<"in ‘swap’:a="<<a<<",b="<<b<<endl;
}
main()
{
int a=3,b=5;
cout<< "before ‘swap’:a="<<a<<",b="<<b<<endl;
swap(a,b);
cout<<"after ‘swap’:a="<<a<<",b="<<b<<endl;
}
引用可以看作是一個變數的別名,使用 引用 時 ,對於void swap(int a,int b) 編譯器並沒有給形參a,b分配新的記憶體空間,只是使形參a,b指向了main函式中實參a,b的記憶體空間,他們共享同一內空間,即把地址給了形參。所以在void swap(int a,int b)函式中對這塊記憶體的改變也就改變了實參的值。
除了使用引用,也可以使用指標。
指標方式和引用方式都屬於傳址呼叫。
兩種引數都允許函式修改實參所對應的物件,兩種型別的引數都允許有效得向函式傳遞大型類物件。
兩者在引數傳遞過程中,有如下幾點不同
(1)引用必須被初始化為指向一個物件,一旦初始化了,它就不能在指向其它物件。指標可以指向一系列不同的物件,當然也可以定義為NULL;
如:
calss Type{ void operation(const Type&p1,const Type&p2); int main(){ Tyoe obj1; Type obj2 = operation(obj1,0); //引用引數的實參不能為0 } |
所以在函式中,一個引數可能指向不同的物件的情況,或者這個引數可能不指向任何物件,則必須實用指標引數。
(2)引用引數的一個重要用法,它允許我們在有效實現過載操作符的還能保證用法的直觀性。如下例:
Matrix operator+(Matrix m1,Matrix m2) { Matrix result; //do computation return result; } |
通過上面實現後,就能夠支援兩個Matrix物件的加法,如:a+b
但是這樣做,效率會非常低。因為該實現的實參是按值傳遞,兩個Matrix物件相加的時候,內容被拷貝到operator+()函式的引數區中,因為Matrix物件非常大的時候,分配這樣一個物件,並把它拷貝到函式引數區中的時間和空間開銷比較高。
而為了提高我們的操作符函式的效率,假定我們決定把引數申明為指標的時候,如下:
Matrix operator+(Matrix *m1,Matrix *m2) { Matrix result; //do computation return result; } |
這種做法,在一定程度上很好得解決了函式實現的效率問題,但是帶來一個新的問題是使用者的使用習慣,對於這樣的operator+操作,呼叫方式變為:&a+&b,這樣大大顛覆了我們傳統的呼叫方式。
所以這時候,如果申明為引用的方式,就能到達到效率和使用習慣的目的:
Matrix operator+(Matrix &m1,Matrix &m2) { Matrix result; //do computation return result; } |