【C++基础】第十九课:多维数组

多维数组

Posted by x-jeff on August 28, 2020

【C++基础】系列博客为参考《C++ Primer中文版(第5版)》C++11标准)一书,自己所做的读书笔记。
本文为原创文章,未经本人允许,禁止转载。转载请注明出处。

1.前言

严格来说,C++语言中没有多维数组,通常所说的多维数组其实是数组的数组。

当一个数组的元素仍然是数组时,通常使用两个维度来定义它:

1
2
int ia[3][4];//大小为3的数组,每个元素是含有4个整数的数组
int arr[10][20][30]={0};//将所有元素初始化为0

按照由内而外的顺序阅读此类定义有助于更好地理解其真实含义。

对于二维数组来说,常把第一个维度称作,第二个维度称作

2.多维数组的初始化

和普通数组一样,可以使用花括号初始化多维数组:

1
2
3
4
5
int ia[3][4] = {
        {0, 1, 2,  3},//第1行的初始值
        {4, 5, 6,  7},//第2行的初始值
        {8, 9, 10, 11}//第3行的初始值
};

其中内层嵌套着的花括号并非必需的,例如:

1
2
//和之前的初始化语句是等价的
int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

在初始化多维数组时也并非所有元素的值都必须包含在初始化列表之内。如果仅仅想初始化每一行的第一个元素,通过如下的语句即可:

1
2
3
int ia[3][4]={
	{0},{4},{8}
};

其他未列出的元素执行默认值初始化。

1
2
//只显式地初始化第1行,其他元素执行默认值初始化
int ia[3][4] = {0, 3, 6, 9};

3.多维数组的下标引用

1
2
3
4
//用arr的首元素为ia最后一行的最后一个元素赋值
ia[2][3] = arr[0][0][0];
//把row绑定到ia的第二个4元素数组上
int (&row)[4] = ia[1];

使用多层嵌套的for循环来处理多维数组的元素:

1
2
3
4
5
6
7
constexpr size_t rowCnt = 3, colCnt = 4;
int ia_4[rowCnt][colCnt];
for (size_t i = 0; i != rowCnt; ++i) {
    for (size_t j = 0; j != colCnt; ++j) {
        ia_4[i][j] = i * colCnt + j;
    }
}

4.使用范围for语句处理多维数组

1
2
3
4
5
6
7
8
//使用范围for语句处理多维数组
size_t cnt=0;
for(auto &row : ia){
    for(auto &col : row){
        col=cnt;
        ++cnt;
    }
}

⚠️第一个for循环遍历ia的所有元素,这些元素是大小为4的数组,这里的row必须定义成对数组的引用,因为row如果不是引用类型,编译器初始化row时会自动将这些数组形式的元素转换成指向该数组内首元素的指针,这样得到的row的类型就是int *,显然内层的循环就不合法了。

第二个for循环遍历那些4元素数组中的某一个,因此col的类型是整数的引用。

‼️要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型

5.指针和多维数组

❗️当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针。

1
2
3
int ia[3][4];
int (*p)[4]=ia;//相当于:int (*p)[4]=&ia[0];
p=&ia[2];

注意区分int (*p)[4]int *p[4]

通过使用auto或者decltype就能尽可能地避免在数组前面加上一个指针类型:

1
2
3
4
5
6
for (auto m = ia; m != ia + 3; ++m) {
    for (auto n = *m; n != *m + 4; ++n) {
        cout << *n << " ";
    }
    cout << endl;
}

当然,使用标准库函数beginend也能实现同样的功能,而且看起来更简洁一些:

1
2
3
4
5
6
for (auto m = begin(ia); m != end(ia); m++) {
    for (auto n = begin(*m); n != end(*m); n++) {
        cout << *n << " ";
    }
    cout << endl;
}

6.类型别名简化多维数组的指针

读、写和理解一个指向多维数组的指针是一个让人不胜其烦的工作,使用类型别名能让这项工作变得简单一点儿,例如:

1
2
3
4
5
6
7
8
using int_array=int[4];
typedef int int_array[4];//该语句等同于上一条语句,二选一即可
for (int_array *m = ia; m != ia + 3; ++m) {
    for (int *n = *m; n != *m + 4; ++n) {
        cout << *n << " ";
    }
    cout << endl;
}