有關C++引數傳值的一個問題探討

鴨脖發表於2012-10-24

今天看系統程式設計的時候看到一個程式,思來想去感覺最後的結果跟自己想的不太一樣.後來終於弄明白了,現在貼上:

#include <stdio.h>

void Initialize (char * a, char * b)
{
        a[0] = 'T'; a[1] = 'h'; a[2] = 'i';
        a[3] = 's'; a[4] = ' '; a[5] = 'i';
        a[6] = 's'; a[7] = ' '; a[8] = 'A';
        a[9] = '\0';
        b = a;
        b[8] = 'B';
}

#define ARRAY_SIZE 10
char a[ARRAY_SIZE];
char b[ARRAY_SIZE];

int main(int argc, char * argv[])
{
        Initialize(a, b);
        printf("%s\n%s\n", a, b);
        return 0;
}
源程式就是這個樣子的,那麼輸出結果是this is B,但是b陣列列印出來卻是空的.是這樣的,在我的印象中,凡是涉及到地址操作的,那肯定改變的就是物件本身而不是物件的一個複製品,所以這裡我很不可思議,到底是哪裡想錯了呢?ab陣列初始時都是空的,這肯定是沒有問題的,可是既然b被賦值為a,那麼ab現在的地址都是一樣的,那麼對b的操作肯定也是對a的操作,而且最後列印出來的應該是一樣的,為什麼b是空的呢?


原來,這個函式傳遞進去的引數是一個基礎型別指標型別,那麼其實傳遞到函式棧中的是ab陣列首地址的一個複製品,那麼在函式體中其實都是些臨時變數.b=a是將b陣列首地址的一個複製的臨時變數賦值為a陣列的首地址的一個複製的臨時變數.這個時候對b進行操作,其實是對a陣列進行操作,但是b陣列的實際首地址是沒有發生任何變化的,因為穿進去的只是b陣列的一個複製品,所以當程式從這個函式體中推出的時候,b陣列的首地址還是原來的首地址,那麼它之後的記憶體單元中的值當然是沒有發生任何變化的,都是被值為零的.

但是這個程式的用意明顯是對ab陣列同時進行初始化,那麼這個該怎麼做呢?當然是進行深複製.也就是說我們不能改變陣列的首地址,而是直接根據複製的臨時中間變數來對陣列單元進行操作,從而改變陣列中的內容.改寫後的程式如下所示:

void Initialize (char * a, char * b)
{
        int i;
        a[0] = 'T'; a[1] = 'h'; a[2] = 'i';
        a[3] = 's'; a[4] = ' '; a[5] = 'i';
        a[6] = 's'; a[7] = ' '; a[8] = 'A';
        a[9] = '\0';
        for (i = 0; i < ARRAY_SIZE; i++) 
        {
            b[i] = a[i];
        }
        b[8] = 'B';
}

相關文章