多維動態陣列在C中,大概只能用malloc,但這在一維時尚不構成問題,但需要多維陣列時怎麼辦呢?這算是程式論壇最常被問到的問題之一了。 我把它整理了相關的回覆,都只用二維做說明,更多維的陣列類推即可。就從C談起吧!

動態產生一個[m][n]陣列 Array 的方法
int **Array;
Array= (int **)malloc(m*sizeof(void *));
for (int i=0; i     Array=(int *)malloc(n*sizeof(int *));

這樣你就有一個 int Array[m][n]; 可以用了,是C喔!不是 C++,但這不夠好,若你要的是一個較大的m*n陣列,那麼太多的malloc會使記憶體碎片化(memory fragment)!沒關係,窮則變,變則通!問題既出在for loop不斷的 memory allocation,就從那兒下手:
int **Array, *pData;
Array= (int **)malloc(m*sizeof(int *));
pData= (int *)malloc(m*n*sizeof(int));
for (int i=0; i     Array[i]=pData;

注意到嗎?這次只用了二次的malloc。當要release memory也只要free Array[0] 和 Array 就成了(注意先free Array[0] 再 free Array)!如果嫌兩個alloc/free還是太多,也可簡單併成一個:
int **Array, *pData;
Array= (int **)malloc(m*sizeof(int *)+m*n*sizeof(int));
for (int i=0,pData= (int *)(Array+m); i     Array[i]=pData;

 要 free 時只要 free Array 就行了,帥吧?

 

 

如果用的是C++,那可用的方法就更多了!

《幼幼班》嘗試錯誤的階段
int Array[][] = new int [10][20];    //這樣行ㄇ?
當然不行!int Array[][]不是一個指標,而且只能有一維為不定大小。

 

《小班》終於會從1數到100了
那... int *Array[] = new int [10][20];    //這樣行ㄇ?
有點想法了!但可惜的是 '*' 在 C++的語法是修飾前面的識別字,所以 int *Array[]的意思是 "Array是一個 int 指標的一維陣列!"

如果能使那個 '*' 以獨立指標型態去宣告Array,就會變成"Array是一個指標,指向一維 int 的陣列",而我們知道指標本身就可以當做一維的陣列,那麼是不是就成了"Array是一個二維的int陣列"?

對了!這正是我們要的!問題是怎麼讓'*'成為獨立指標型態,不會去修飾前面的int識別字?答案是使用括號:
int (*Array)[20] = new int [10][20];    //這是正解!

但問題又來了, new 運算子可以使用 new int [m][n],但int (*Array)[20] 的 [20]卻沒辦法以 [n] 來取代,所以就沒辦法做到不定大小的宣告了。所以這只能算是小班的答案,要做到不定大小的動態多維宣告,加上 STL 的運用,是不錯的想法。

 

《中班》vector模板的運用
vector *array=new vector[m];
for (int i=0; i
嘿嘿...不錯吧!?不定大小的二維陣列,而且每個維度還可以隨時調整大小喔!不過還是有缺點ㄟ!那行 for loop 看起來有點礙眼,不能
拿掉嗎?拿掉的話,基本上Array 還是二維陣列,但第二維並沒有預留空間放東西你可以用push.back等成員函式來增加空間和存放data,但不能在還沒有空間時使用像array[5][3]=3; 這種陣列的存取方式。沒更好的方法了嗎?vector不是有預留空間大小的建構子嗎?像一維的宣告:
vector *Array= new vector (n);    //這不是預留了 n 個元素的陣列了嗎?

只可惜,這是一維的宣告,若你嘗試做這樣的宣告:
vector *Array= new vector [m](n);

編譯器會給你無情的嘲諷:陣列不能呼叫帶參數的建構子!這是很令人失望的!為十麼不行?不是邏輯的問題,或許下一版本的C++會可以這樣宣告吧!但為今之計只能自力救濟了。

 

《大班》使用模板在模版中
vector< vector > Array(m, vector(n));

不用懷疑!這是相當於宣告一個動態二維不定大小的 int Array[m][n];

不相信的話你可以在m,n範圍內存取 Array[i][j] 看看。若你能一眼看出這是在幹嘛,那麼你早已超出大班的程度了!若你暫時不知所云,也沒關係,你可以安全的使用它帶給你的好處,只是你也只好留在大班留班查看了。 ^_^

解釋這個宣告,其實不難,但首先你要對模版的使用有相當的了解,當然還要對 vector 模版的建構子不能陌生。這樣子自然很容易可以看得懂它。了然於胸了嗎?恭喜你,大班可以畢業了。 ^_^

註:大班的答案是Duncan在練功房提出的解答,注意到兩個兩個角括號中間的空白了嗎?(> >),因為如果不加空白的話會被語法解析為右移運算子。

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 newmodel 的頭像
    newmodel

    冰戀物語部落格

    newmodel 發表在 痞客邦 留言(0) 人氣()