二维(多维)数组


一维数组使用数组名称与一个索引值来指定访问数组元素,二维数组使用数组名称与两个索引值来指定访问数组元素,定义方式与一维数组类似:

int maze[5][10];

上面这个定义会配置 5 * 10 = 50 个整数的内存空间给数组来使用,二维数组使用两个索引值来指定访问数组,这两个索引值都是由 0 开始,下面这个程序简单的示范二维数组的访问:

#include <iostream> 
using namespace std; 

int main() { 
    constexpr int ROWS = 5;
    constexpr int COLUMNS = 10;
    int maze[ROWS][COLUMNS]; 

    for(int row = 0; row < ROWS; row++) {
        for(int i = 0; i < COLUMNS; i++) {
            maze[row][i] = (row + 1) * (i+ 1);
        }
    } 

    for(int row = 0; row < ROWS; row++) {
        for(int i = 0; i < COLUMNS; i++) {
            cout << maze[row][i] << "\t"; 
        }
        cout << endl; 
    } 

    return 0; 
}

执行结果:

1       2       3       4       5       6       7       8       9       10      
2       4       6       8       10      12      14      16      18      20      
3       6       9       12      15      18      21      24      27      30
4       8       12      16      20      24      28      32      36      40
5       10      15      20      25      30      35      40      45      50

上面这个程序定义了 5 列(Row)、10 行(Column)的数组,第一个[]是用来指定访问哪一列,第二个[]是用来指定访问哪一行。

可以在定义二维数组的同时指定二维数组的值,例如:

int maze[2][3] = {
                     {1, 2, 3},
                     {4, 5, 6}
                 };

从上面这个程序来看,可以清楚地看出maze[2][3]中 2 与 3 的意义,maze[2]表示maze有两个元素,各是{1, 2, 3}{4, 5, 6},也就是说,这两个元素是一维数组,而长度是 3。

若清楚二维数组的内存配置方式,会理解到{}其实是可以不用的,例如:

int maze[2][3] = {
                     1, 2, 3,
                     4, 5, 6
                 };

何谓二维数组于内存中的配置方式?其实二维数组访问时的行与列,只是为了便于理解数组元素索引,索引值真正的意义,还是〈一维数组〉中谈到的,是指相对于数组第一个元素的位移量,例如,在一维数组中的数组配置与索引意义如下图所示(若int长度为 4 个字节):

二维(多维)数组

int数组来说,每次位移量是 4 个字节,指定访问maze[4],相当于指定访问相对于maze[0]四个位移量的内存空间。

二维数组在内存中也是线性配置,例如:

二维(多维)数组

在上面的例子中,二维数组将得到的内存分为两个区块,定义数组maze[2[4],表示maze[0][0]maze[1][0]相对位移量为 4,访问maze[1][3]时,表示访问位置相对于maze[1][0]位移3个单位。

若定义maze[3][5]的话,内存位置的指定是如何呢?在这个数组中 5 的意义是maze[0][0]maze[1][0]maze[2][0]间都是 5 个位移量,如下图所示:

二维(多维)数组

了解二维数组在内存中的配置关系后,就可以知道,上图可以看成是三个一维数组在内存中连续配置,严格来说,C++ 没有二维数组这种东西,二维或多维数组的概念,是以数组的数组(arrays of arrays)来实现。

在 C++ 11 新增了 for range 语法,可以使用这个语法来验证所谓的二维数组,就是具有两个一维数组作为元素的数组:

#include <iostream> 
using namespace std; 

int main() { 
    int maze[2][3] = {
                         {1, 2, 3},
                         {4, 5, 6}
                     };

    for(auto row : maze) {
        for(int i = 0; i < 3; i++) {
            cout << row[i] << "\t"; 
        }
        cout << endl; 
    } 

    return 0; 
}

row的类型实际上是int*,这是指针类型,之后会谈到;那么可不可以用两个 for range 来执行相同的任务呢?这需要知道参考(reference)是什么,之后也会谈到,就结论而言,可以如下:

#include <iostream> 
using namespace std; 

int main() { 
    int maze[2][3] = {
                         {1, 2, 3},
                         {4, 5, 6}
                     };

    for(auto &row : maze) {
        for(auto n : row) {
            cout << n << "\t"; 
        }
        cout << endl; 
    } 

    return 0; 
}

更多维的数组,就是依以上说明类推罢了,例如三维数组:

int arr[2][4][6];




展开阅读全文