使用外部函數交換兩個變量的值,一個再簡單不過的事情,但是在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()也是正確的,這是引用的重要應用之一。對於引用的操作實際上是作用在引用所因的對象上。
