現在,要為各位介紹CallByReference進行SWAP的做法。先聲明,CallByReference是在C++才有的概念,不過由於現在Complier幾乎沒有單獨支援C不支援C++的, 所以就算用C語言去寫CallByReference還是可被接受。

我們前面有提過CallByValue和CallByAddress,不管是哪種方法,OS都會再次配置副函式引數所需的記憶體空間,但CallByReference是非常特別的方法,OS是直接跑到主函式a, b的位址直接進行運算,並沒有再配置額外的記憶體。所以也有人說,使用CallByReference的速度會比較快。CallByReference的寫法大致如下:

void swap(int &c, int&d){…..}
void main()
{
     int a, b;
     swap(a, b);
}

在副函式裡面,c所接受的是a的位址值,而OS是不再配置額外記憶體空間,等於是在副函式裡,c只是main裡面 a的另一個名字而已(別名)。同理,b和d的關係也是如此。

程式碼:

// ====================================
// FileName: CallByReference.cpp
// Author  : Edison.Shih.
// Complier: VC 2008

#include <stdio.h>


// ====================================
void Swap_R(int &a, int &b)
{
        int c;
        printf("\n=== swap_R function initial ===\n");
        printf("  a = %6d,  b = %6d\n",     a,  b);
        printf(" &a = %06X, &b = %06X\n",  &a, &b);
        c = a;
        a = b;
        b = c;
        printf("\n=== swap_R function swap end ===\n");
        printf("  a = %6d,  b = %6d\n",     a,  b);
        printf(" &a = %06X, &b = %06X\n",  &a, &b);
}

// ====================================
int main(int argc, char **argv)
{
        int a=10;
        int b=5;

        printf("\n *=== before swap in main ===* \n");
        printf(" a = %6d, b = %6d\n",    a, b);
        printf(" &a = %06X, &b = %06X\n", &a,&b);
        Swap_R(a, b);

        printf("\n *=== after swap in main ===* \n");
        printf("  a = %6d,  b = %6d\n",    a, b);
        printf(" &a = %06X, &b = %06X\n", &a,&b);

        return 0;
}

執行結果:


 *=== before swap in main ===*
 a =     10, b =      5
 &a = 12FF60, &b = 12FF54

=== swap_R function initial ===
  a =     10,  b =      5
 &a = 12FF60, &b = 12FF54

=== swap_R function swap end ===
  a =      5,  b =     10
 &a = 12FF60, &b = 12FF54

 *=== after swap in main ===*
  a =      5,  b =     10
 &a = 12FF60, &b = 12FF54

說明:

在Swap_R(a, b);之前,記憶體配置圖如下

儲存值

5

10

 

……..

……..

……..

記憶體位址

12FF54

12FF60

……..

……..

……..

……..

 

主函b

主函a

 

 

 

 

 

在剛進入 Swap_R(a, b)時,OS就不再配置位置。而且進行直接性的操作,所以記憶體配置圖從頭到尾都是一樣的。

儲存值

10

5

 

……..

……..

……..

記憶體位址

12FF54

12FF60

……..

……..

……..

     ……..

 

主函b

主函a

 

 

 

 

 

副函b

副函a

 

 

 

 

 

CallByValue、CallByAddress、CallByReference的解說到此結束。要提醒各位,什麼情況下要用CallByValue 還是CallByAddress、CallByReference,最主要的理由是在於,你要不要你 main()裡面的變數被副函式變更。

arrow
arrow
    全站熱搜

    Edison 發表在 痞客邦 留言(3) 人氣()