C 中的動態多維陣列

2021-04-13 09:21:03 字數 2752 閱讀 6781

前言]c++的new操作符是該語言乙個非常好的語法特性,然而實際使用中卻發現new操作符有不少限制,為突出的一點便是用new操作符分配多維陣列空間時,不能讓陣列的每一維都動態可變。本文將對此提出乙個簡單直觀的解決方案,在乙個實際問題的簡化模型中加以說明,並以此釋清許多初學者對c++中new操作符與多維陣列的誤區。

1.問題的提出--多維可變陣列的實際用途

下面是實際程式設計中遇到問題的乙個簡化模型。chessboard是乙個棋盤類,其中的m_board是用來儲存棋盤上棋子資訊的二維陣列。dimension是棋盤的尺寸或者維數,因為要用於陣列宣告,所以它必須是乙個編譯期間可以確定其值的常量,這裡我們使用了無名列舉。對於不同種類棋的棋盤大小是不同的,對於黑白棋,dimension定義為8,對於五子棋,dimension應該為15,而圍棋呢,又得是19。對此這段**採用了條件編譯來確定dimension常量的值,以保證這段**具有較好的可重用性。

由於m_board必須是編譯期常量,於是在程式執行時刻m_board陣列的大小是不可改變的。如果程式中要同時實現黑白棋、五子棋和圍棋就不能這樣來做了--當然這樣有點誇張,不過就算光是圍棋也有9x9、13x13、19x19幾種棋盤,而且應當能讓使用者在程式執行時自由選擇。

class chessboard

;int m_board[dimension][dimension];

public:

/*其它成員函式

......*/}

對此我們必須用new操作符或者malloc函式在程式執行時刻為m_board動態分配空間,由於new支援更多的c++特性,因此我們的程式採用了new操作符。

2.msdn中用new申請多維陣列的說明--進一步認識new操作符

下面的**摘自msdn中的「new operator」,其中第二行在vc6.0中編譯將得到乙個錯誤資訊,對此msdn中的說明是new操作符返回的型別為float(*)[25][10],即指向float[25][10]的指標(去掉最左邊的一維)。正確**應當如3、4行所示。

1. float *fp;

2. fp = new float[10][25][10]; //錯*'

3. float (*cp)[25][10];

4. cp = new float[10][25][10];誤資訊:cannot convert from 'float (*)[25][10]' to 'float

int (*m_board)[dimension]; //在類的成員變數中宣告

m_board = new int[changeable][dimension]; //根據使用者選擇來確定相應的changeable值

不難看出,由於仍然必須用編譯期常量dimension來宣告陣列,所以m_board陣列只能有一維可變,這種方法對我們的問題是毫無用處的。

3.解決方案

這裡給出兩種解決方案,並對第二種方案給出具體**。

1). 我們可以申請大小為xsize*ysize的一維陣列,然後自己通過對xy下標換算來定位相應的儲存單元,**如下:

int *p=new int[ysize*xsize]; file://xsize和ysize應該定義為常量

file://但是對於p[y][x]的引用便成了語法錯誤,應該為

p[y*xsize + x]=y*1000 + x;

這種方法最大的好處是陣列維數可以自由確定,甚至可以動態確定,因為都是轉換為一維陣列。但是它的最大的不便之處就是下標轉換的繁瑣,在多維陣列的情況下更為明顯。如下面這段**是一段檢驗下標轉換是否正確的程式,其輸出結果應該為每個陣列單元的位址都不相同,而且都落在「開始位址」和「結束位址」之間。

const int ysize=6;

const int xsize=7;

const int zsize=9;

int *p=new int[ ysize*xsize*zsize ];

file://但是對於p[y][x]的引用便成了語法錯誤,應該為

可以看到其中的陣列p僅僅是乙個三維陣列的但是其下標轉換z*ysize*xsize+y*xsize+x已經相當繁瑣了,使用上的繁瑣常常會成為程式中bug的**。因此這種方法對初學者並不適用,但它的靈活性與簡單性使我們不能忽視它。利用這種方法可以將多維陣列封裝成乙個通用類,不但可以動態改變陣列每一維的大小,而且連陣列的維數都可以動態改變(這個通用陣列類正在筆者的計畫之中)。

2).將多維陣列當作多個一維陣列

這裡我們直接給出前面提出棋盤類問題的**,建構函式chessboard、析構函式~chessboard和輸出函式output中分別對應給出了二維陣列m_board的空間分配,空間釋放和單元引用的相關**。而且可以看出雖然這種方法需要用迴圈來分配、釋放空間並且需要額外的儲存空間,但從output函式可以看到,它的使用與常規陣列使用的語法是一致的,較上面的第一種方法繁瑣的下標轉換要方便得多。

由於**並不複雜,除了**中的注釋外,就不再另外詳細說明。雖然這裡給出的是二維陣列,但也不難將其擴充到多維陣列。其中m_board陣列的資料結構可以直觀的由圖一看到。

圖一、陣列m_board的資料結構

class chessboard;

chessboard::chessboard(int boardsize=8):

dimension(boardsize)}}

chessboard::~chessboard()

delete m_board;

}void chessboard::output()}}

}

C 中的動態多維陣列

前言 c 的new操作符是該語言乙個非常好的語法特性,然而實際使用中卻發現new操作符有不少限制,為突出的一點便是用new操作符分配多維陣列空間時,不能讓陣列的每一維都動態可變。本文將對此提出乙個簡單直觀的解決方案,在乙個實際問題的簡化模型中加以說明,並以此釋清許多初學者對c 中new操作符與多維陣...

動態多維陣列

寫 的時候會碰到多維陣列的記憶體分配和釋放問題,在分配和釋放過程中很容易出現錯誤。下面貼上一些示例 以供參考。如果要給二維陣列 m n 分配空間,可以寫成下面 char a,i 先分配m個指標單元,注意是指標單元 所以每個單元的大小是sizeof char a char malloc m sizeo...

動態定義多維陣列

1.普通陣列的定義 維數 const unsigned int buf size 512,max files 20 int staff size 27 const unsigned sz get size char input buffer buf size ok,是const變數 string f...