Pages

2011年6月9日 星期四

[C++] 動態陣列擴充時,容易犯錯的指標傳遞

        在動態擴充陣列大小時,如果透過很多函式來傳遞,要注意指標的問題。
        舉例來說,寫一個函式Expand用來擴充陣列,需傳給此函式一個指標代表陣列,然而如果宣告參數時只寫一個星號,則Expand內部會自動產生一個新的指標(假設叫做A)並將傳遞進來的指標(假設叫做B)內所存的位址複製一份在新的指標變數A內。
        在這種情況下要注意,如果在Expand內將A指標指向一個新的位址,那麼就指標B並沒有指向新的位址,這是容易讓程式當掉的地方。
        因此Expand可以在宣告參數時,給予參數兩個星號,如此傳遞進來的,就是B指標的位址,因此只要更改此位址指向的那個位置,就可以把原來傳遞進來的陣列更改。
用言語表達此觀念似乎不太清楚,用實例來表達如下:
以下是我打的一個範例程式碼:
//////////////////////////////////////////////////////
#include<iostream>
using namespace std;
void Expand1(int **arrReceive,int &size,int key)
{
    int *old = *arrReceive;
    *arrReceive = new int [size+1];
    for(int i=0;i<size;i++)
    {
        (*arrReceive)[i] = old[i];
    }
    (*arrReceive)[size] = key;
    size++;
    delete []old;
}
int *Expand2(int *arrReceive,int &size,int key)
{
    int *newArr = new int [size+1];
    for(int i=0;i<size;i++)
    {
        newArr[i] = arrReceive[i];
    }
    newArr[size] = key;
    delete []arrReceive;
    size++;
    return newArr;
}
void changeArr(int **arrReceive,int &size)
{
    Expand1(&(*arrReceive),size,123);
    (*arrReceive) = Expand2(*arrReceive,size,456);
}
int main()
{
    int size = 3;
    int *a = new int [size];  //不能寫int a[] = {1,2,3}; 會有問題。
    cout << "original array:" << endl;
    for(int i=0;i<size;i++)
    {
        a[i] = i;
        cout << " " << a[i];
    }
    cout << endl;
    changeArr(&a,size);
    cout << "after change:" << endl;
    for(int i=0;i<size;i++)
    {
        cout << " " << a[i];
    }
    cout << endl;
}
//////////////////////////////////////////////////////////
執行結果>>
original array:
0 1 2
after change:
0 1 2 123 456


Expand1跟Expand2的都可以安全的擴充陣列。
1.   Expand1是:將指向原陣列第一個元素的指標,這個指標有一個位址,把這個位址丟給Expand1來接,Expand1會產生一個新的指標並把這個位址指向的位址做更改。因此元陣列整個都被更改了。
2.   Expand2是直接在Expand2函式內產生一個新的陣列指標,並把舊的陣列指標指向的地方delete,回傳新的指標給原指標接收,也可以擴充陣列。

沒有留言:

張貼留言