作者:
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);