作者:
2009年2月3日

多維陣列

得分: 3.6/5 (86 票)
*****
這是另一個經常被問到的主題。
- 如何建立二維/三維陣列?

當我開始處理多維陣列時,發現很難找到我想要的答案。所以我將釋出一些資訊,希望能幫助到其他人。我將介紹兩種主要的方法(Vector vs 指標)。

基於 Vector 的多維陣列 Vector 是一個 STL 容器,允許您在其中儲存幾乎任何東西。正確使用時,它們是非常強大的容器。

它們提供了一個額外的優勢,那就是當它們離開作用域時,它們會自動釋放所佔用的記憶體。這意味著儲存在 vector 中的物件不需要被釋放(但指向物件的指標需要)。

您還可以使用 vector 來處理動態多維陣列。例如,如果您只分配了第一維,然後使用 .push_back() 向第二維新增記錄,那麼它就不再是網格,而是一個具有動態大小的第二維的陣列(就像一條街道,每棟建築有不同的樓層數)。使用指標也可以實現這種功能,但難度要大得多。

使用 vector 的簡單二維陣列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
using std::vector;

#define HEIGHT 5
#define WIDTH 3

int main() {
  vector<vector<double> > array2D;

  // Set up sizes. (HEIGHT x WIDTH)
  array2D.resize(HEIGHT);
  for (int i = 0; i < HEIGHT; ++i)
    array2D<i>.resize(WIDTH);

  // Put some values in
  array2D[1][2] = 6.0;
  array2D[3][1] = 5.5;

  return 0;
}


使用 vector 的三維陣列。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <vector>
using std::vector;

#define HEIGHT 5
#define WIDTH 3
#define DEPTH 7

int main() {
  vector<vector<vector<double> > > array3D;

  // Set up sizes. (HEIGHT x WIDTH)
  array3D.resize(HEIGHT);
  for (int i = 0; i < HEIGHT; ++i) {
    array3D<i>.resize(WIDTH);

    for (int j = 0; j < WIDTH; ++j)
      array3D<i>[j].resize(DEPTH);
  }

  // Put some values in
  array3D[1][2][5] = 6.0;
  array3D[3][1][4] = 5.5;

  return 0;
}


基於指標的多維陣列 基於指標的多維陣列為您提供了更底層的物件訪問許可權。其好處是可以提高速度,並且您可以對其應用自定義最佳化。

注意:您可以透過將兩個維度組合成一個維度(HEIGHTxWIDTH)來最佳化這一點。我將省略這方面的討論,因為這是一個更高階的話題,適合已經熟悉該主題的人。

一個簡單的二維陣列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define HEIGHT 5
#define WIDTH 3

int main() {
  double **p2DArray;

  // Allocate memory
  p2DArray = new double*[HEIGHT];
  for (int i = 0; i < HEIGHT; ++i)
    p2DArray<i> = new double[WIDTH];

  // Assign values
  p2DArray[0][0] = 3.6;
  p2DArray[1][2] = 4.0;

  // De-Allocate memory to prevent memory leak
  for (int i = 0; i < HEIGHT; ++i)
    delete [] p2DArray<i>;
  delete [] p2DArray;

  return 0;
}


一個三維陣列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#define HEIGHT 5
#define WIDTH 3
#define DEPTH 7

int main() {
  double ***p2DArray;

  // Allocate memory
  p2DArray = new double**[HEIGHT];
  for (int i = 0; i < HEIGHT; ++i) {
    p2DArray<i> = new double*[WIDTH];

    for (int j = 0; j < WIDTH; ++j)
      p2DArray<i>[j] = new double[DEPTH];
  }

  // Assign values
  p2DArray[0][0][0] = 3.6;
  p2DArray[1][2][4] = 4.0;

  // De-Allocate memory to prevent memory leak
  for (int i = 0; i < HEIGHT; ++i) {
    for (int j = 0; j < WIDTH; ++j)
      delete [] p2DArray<i>[j];

    delete [] p2DArray<i>;
  }
  delete [] p2DArray;

  return 0;
}


最後一點需要注意。當使用自定義物件型別建立動態陣列時,您不能過載建構函式。ISO 標準禁止這樣做,您必須稍後初始化物件的值。分配到陣列中的所有物件都必須使用預設建構函式。

上面的程式碼片段在 Windows 和 Linux 上都可以毫無問題地編譯。

建議 除非您的應用程式有極端的需求來進行高度最佳化,並且您對 C++ 記憶體管理非常精通,否則您應該使用基於 vector 的方法。這種方法更容易管理,尤其是當您剛開始學習 C++ 時。
您可以透過指標傳遞它們。

例如
void doSomethingWith2D(double **Array);
void doSomethingWith2D(vector<vector<double> > &Array);