C++學習筆記(二)——交換函數(swap)
這次我們要透過一個簡單的函數swap深入理解函數傳參的本質以及在C++中如何選擇傳參方式。
先來看第一段程序:
void swap(int x, int y) { int temp = y; y = x; x = temp; }
通過main函數的調用,我們發現x,y並未實現交換:
int main() { int x = 1; int y = 37; swap(x, y); cout << x << ":" << y << endl; return 0; }
原因是整形x和y在函數swap內為按值傳遞,按值傳遞時,函數不會訪問當前調用的實參。函數處理的值是它本地的拷貝,這些拷貝被存儲在運行棧中,因此改變這些值不會影響實參的值。一旦函數結束了,函數的活動記錄將從棧中彈出,這些局部值也就消失了。
在按值傳遞的情況下,實參的內容沒有被改變。這意味著程序員在函數調用時無需保存和恢復實參的值。如果沒有按值傳遞機制,那麽每個沒有被聲明為const 的參數就可能會隨每次函數調用而被改變。按值傳遞的危害最小,需要用戶做的工作也最少。毫無疑問,按值傳遞是參數傳遞合理的缺省機制。
另外,如果作為實參的變量是一個大型類的對象,分配並拷貝到棧中的時間和空間開銷往往過大。
要實現swap函數的效果,我們應如何處理呢?第一個可行的做法是將形參聲明成指針:
void pswap(int *x, int *y) { int temp = *y; *y = *x; *x = temp; }
在pswap函數中,由於傳遞的是兩個變量的內存地址(指針)使得我們可以直接操作對應的值。實際上這裏還是存在按值傳遞的問題,只是由原先的整形傳遞變成了指針傳遞。我們可以修改指針指向的內存卻依然無法修改指針本身。第二個可行的做法是想形參聲明為指針的引用:
void prswap(int *&x, int *&y) { int temp = *y; *y = *x; *x = temp; } void prswap(int *&x, int *&y) { int *temp = y; y = x; x = temp; }
請註意,同一個函數原型下我提供了兩種函數定義。可無論哪一種,在實參傳遞的階段都不會發生按值傳遞的問題。那麽兩種定義到底哪一種更滿足我們需求:
(1)交換內存中的值
(2)交換指針地址
如果單獨考慮本文的需求,第一種方法更滿足。但是,如果我們需要交換的是一個大型類對象,第二種的效率則更高。
總結:內存管理是C++學習的一個難點,初學者往往不容易掌握。但越是如此就越能體現一個開發者的語言內功。
C++學習筆記(二)——交換函數(swap)