1. 程式人生 > >C++學習筆記(二)——交換函數(swap)

C++學習筆記(二)——交換函數(swap)

pos 變量 col 值傳遞 一段 turn 如何選擇 ret 原因

這次我們要透過一個簡單的函數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)