使用外部函數交換兩個變量的值,一個再簡單不過的事情,但是在C/C++中,正確實現該功能反應了你對指針和引用等重要知識的掌握程度。本文列舉了幾種常見的寫法,其中前三種是錯誤的,后兩種是正確的。第四種使用的是指針,第五種使用的是引用。請看下面五個簡單的函數:
- #include<iostream>
 - using namespace std;
 - int fun1 (int a,int b)
 - {
 - int c;
 - c=a;a=b;b=c;
 - cout<<"a1:"<<a<<";b1:"<<b<<endl;
 - }
 - int fun2 (int *a,int *b)
 - {
 - int *c;
 - c=a;a=b;b=c;
 - cout<<"a2:"<<*a<<";b2:"<<*b<<endl;
 - }
 - int fun3(int *a,int *b)
 - {
 - int *c;
 - c=*a;*a=*b;*b=c;
 - cout<<"a3:"<<*a<<";b3:"<<*b<<endl;
 - }
 - int fun4 (int *a,int *b)
 - {
 - int c;
 - c=*a;*a=*b;*b=c;
 - cout<<"a4:"<<*a<<";b4:"<<*b<<endl;
 - }
 - int fun5 (int &a,int &b)
 - {
 - int c;
 - c=a;a=b;b=c;
 - cout<<"a5:"<<a<<";b5:"<<b<<endl;
 - }
 - int main()
 - {
 - int aa=1,bb=2;
 - fun1(aa,bb);
 - cout<<"aa1:"<<aa<<";bb1:"<<bb<<endl;
 - fun2(&aa,&bb);
 - cout<<"aa2:"<<aa<<";bb2:"<<bb<<endl;
 - fun3(&aa,&bb);
 - cout<<"aa3:"<<aa<<";bb3:"<<bb<<endl;
 - fun4(&aa,&bb);
 - cout<<"aa4:"<<aa<<";bb4:"<<bb<<endl;
 - aa=1,bb=2;
 - fun5(aa,bb);
 - cout<<"aa5:"<<aa<<";bb5:"<<bb<<endl;
 - return 0;
 - }
 
輸出結果為:
- a1:2;b1:1
 - aa1:1;bb1:2
 - a2:2;b2:1
 - aa2:1;bb2:2
 - aa3:1;bb3:2
 - a4:2;b4:1
 - aa4:2;bb4:1
 - a5:2;b5:1
 - aa5:2;bb5:1
 
fun1(),如果使用Java或者其它高級語言,使用該函數沒什么問題,甚至是天經地義的,但是C和C++里卻不行,原因是main中調用fun1()時,將實參a,b的值傳遞給了交換函數,如果此時在swap1中打印,可以看到結果是正確的,但是該過程其實是將aa和bb分別復制了一份給了函數,執行完fun1()之后,aa和bb的值沒有任何變化。
fun2(),看似的確使用了指針,但任然失敗,為什么呢?其實這里是將aa和bb的地址給交換了,而並沒有交換aa和bb的值。在這里由於未給c賦值,c中並沒有確定的值,c中的值是不可預見的。此時c可能指向一個未知的存儲單元。而嚴重的情況是,該單元的數據可能是有用的,因此fun2()不但沒有實現兩個數的交換,反而給系統的穩定性帶來威脅。
fun3(),將int賦值給int *,編譯錯誤。c是int *類型,*a、*b、*c是int類型
fun4()是正確的。為了在函數中改變了的變量能被其它函數調用,正確的辦法是用指針變量作為函數參數,在函數執行過程中使指針變量所指向的變量值發生變化,函數調用結束后,哲別變量值的變化依然保留下來,這樣就實現了通過函數調用是變量的值發生變化,在其它函數中可以使用這些改變了的值的目的。
fun5()也是正確的,這是引用的重要應用之一。對於引用的操作實際上是作用在引用所因的對象上。
