c++系列文章(11):多维数组

人盡茶涼 提交于 2020-03-08 09:32:12

  严格来说,C++语言中没有多维数组,通常所说的多维数组其实是数组的数组。当一个数组的元素仍然是数组时,通常使用两个维度来定义它:一个维度表示数组本身大小,另一个维度表示其元素(也是数组)大小。

int ia[3][4]; //大小为3的数组,每个元素是含有4个整数的数组
int arr[10[20[30] = {0}; //大小为10的数组,其个元素是大小为20的数组,这些数组的袁术是含有30个整数的数组,并将虽有元素初始化为0

多维数组的初始化

  允许使用花括号括起来的一组值初始化多维数组。

int ia[3][4] = {
	{0,1,2,3}, //第一行的初始值
	{4,5,6,7}, //第二行的初始值
	{8,9,10,11}, //第三行的初始值
}
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11}; //没有标识每行的花括号,与上面的初始化语句等价

  在初始化多维数组时并非所有元素的值都必须包含在初始化列表之内。

int ia[3][4] = {{0},{4},{8}}; //显式初始化每行的首元素,其他未列出的元素执行默认值初始化
int ia[3][4] = {0,3,6,9}; //如果再省略掉内层的花括号,就变成显式初始化第一行,其他元素执行值初始化

  程序中经常会用到两层嵌套的for循环来处理多维数组的元素。

constexpr size_t rowCnt = 3,colCnt = 4;
int ia[rowCnt][colCnt]; //12个未初始化的元素
for(size_t i = 0; i != rowCnt;++i)
{
	for(size_t j = 0;j != colCnt;++j)
	{
		ia[i][j] = i * colCnt + j;
	}
}
// C++11可以使用范围for来简化
size_t cnt = 0;
for(auto &row:ia)
	for(auto &col:row)
	{
		col = cnt;
		++cnt;
	}

  之所以将外层循环的控制变量声明为引用类型,这是为了避免数组被自动转成指针,假设不用引用类型,则循环如下形式:

for auto row:ia)
	for(auto col:row)

  程序将无法通过编译,这是因为row不是引用类型,所以编译器初始化row时会自动将这些数组形式的元素(和其他类型的数组一样)转换成指向该数组内首元素的指针。这样得到的row的类型就是int*,显然内层的循环就不合法了,编译器将试图在一个int*内遍历,这显然和程序的初衷背离。因此要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型

指针和多维数组

  当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针,因为多维数组实际上是数组的数组,因此由多维数组名转换得到的指针实际上是指向第一个内层数组的指针

int ia[3][4]; //大小为3的数组,每个元素是含有4个整数的数组
int (*p)[4] = ia; //p是指向含有4个整数的数组
 p = &ia[2]; //p指向ia的尾元素

  随着C++11新标准的提出,通过使用auto和decltype就能尽可能地避免在数组前面加上一个指针类型了:

// 输出ia中每个元素的值,每个内层数组各占一行
// p指向含有4个整数的数组
for(auto p = ia; p != ia+3;++p)
{
	// q指向含有4个整数的数组的首元素,也就是说q指向一个整数
	for(auto q = *p;q != *p + 4;++q)
		cout << *q << ' ';
	cout << endl;
}

  内层的for循环负责输出内层数组所包含的值,它首先令指针q指向p当前所在行的第一个元素。*p是一个含有4个整数的数组,像所有类型的数组一样,数组名被自动转换成指向该数组首元素的指针。
  当使用标准库函数hegin和end也能实现同样的功能,而且更加简洁:

// p指向ia的第一个数组
for(auto p = begin(ia); p != end(ia);++p)
	// q指向内层数组的首元素
	for(auto q = begin(*p);q != end(*p);++q)
		cout << *q <<  ' ';
	cout << endl;

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

  读、写和理解一个指向多维数组的指针是一个十分繁琐的工作,使用类型别名能够让这项工作变得简单一点。下面的程序将类型“4个整数组成的数组”命名为int_array:

using int_array = int[4]; //C++11新标准的类型别名声明
typedef int int_array[4]; //等价的typedef声明
for(int_array *p = ia;p != ia+3;++p)
{
	for(int *q = *p;q != *p+4;++q)
		cout << *q << ' ';
	cout << endl;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!