C++ Primer 笔记九 多维数组

C++ Primer 笔记九 多维数组


通常所说的多维数组,其实是数组的数组。

int a[3][4];		// 大小为3的数组,每个元素是大小为4的数组

// 大小为10的数组
// 每个元素是大小为20的数组
// 这些数组的元素是含有30个整数的数组
int a1[10][20][30];	

多维数组的初始化

int ia[2][3] = {{2, 5, 8}, {8, 9, 10}};

等价于

int ia[2][3] = {2, 5, 8, 8, 9, 10};

可以显示地初始化每行的首元素,其他未列出的元素执行默认初始化

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

显示地初始化第一行,其他默认初始化

int ia[2][3] = {2, 5, 8, 8};

多维数组元素的访问
可以使用下标运算符来访问多维数组的元素:

int iarr[2][3][4] = {0};
int  iarr1[3][2];

// 使用iarr的第一个元素为iarr1的最后一行最后一个元素赋值
iarr1[2][1] = iarr[0][0][0];

// 把row绑定到iarr的第二个3元素数组上
int (&row)[3] = iarr[1];

程序中经常用多层嵌套的 for 循环来访问多维数组的元素:

// 示例:使用多层嵌套的for循环输出一个二维数组
// example.cc
#include <iostream>

int main() {
	const unsigned rowCnt = 3, colCnt = 4;
	int ia[rowCnt][colCnt];
	for (size_t i = 0; i != rowCnt; ++i) {
		for (size_t j = 0; j != colCnt; ++j) {
			ia[i][j] = i * colCnt + j;
			std::cout << ia[i][j] << "\t";
		}
		std::cout << std::endl;
	}

	return 0;
}
$ ./example.out 
0	1	2	3	
4	5	6	7	
8	9	10	11	

也可以使用范围 for 来处理多维数组:

// 示例2:使用范围for输出一个二维数组
// example2.cc
#include <iostream>

int main() {
	const unsigned rowCnt = 3, colCnt = 4;
	int ia[rowCnt][colCnt];
	int cnt = 0;
	
	// 因为要改变数组的元素,所以控制变量声明为引用类型
	// 外层数组的每一个元素
	for (auto &row : ia) {
		// 内层数组的每一个元素
		for (auto &col : row) {
			col = cnt;
			++cnt;
			std::cout << col << "\t";
		}
		std::cout << std::endl;
	}
	
	return 0;
}
$ ./example2.out
0	1	2	3	
4	5	6	7	
8	9	10	11	

事实上,使用范围 for 处理多维数组,除了最内层的循环外,其他所有的控制变量都应该是引用类型。
一个错误的例子:

for (auto row : ia) {	// row 的类型为 int*

	// 下面操作将引发错误
	// note : mismatched types ‘_Tp [_Nm]’ and ‘int*’
	for (auto col : row) {
		// ...
	}
}

编译器初始化 row 时会自动将这些数组形式转换成数组内首元素的指针,因此 row 的类型是 int* 。一个正确的例子:

// 将外层循环的控制变量声明成引用类型
for (const auto &row : ia) {
	for (auto col : row) {
		cout << col << endl;
	}
}

指针和多维数组
由多维数组名转换得来的指针实际上是指向第一个内层数组的指针(多维数组是数组的数组):

int ia[3][4];
int (*p)[4] = ia;	// p指含有4个整数的数组,其中圆括号'()'必不可少
p = &ia[2];			// p指向ia的尾元素

C++11允许通过 autodecltype 来简化声明:

// 使用auto
for (auto p = ia; p != ia + 3; ++p) {		// p是一个int[4] *类型
	// 解引用p得到指向内层数组首元素的指针,q是一个int*类型
	for (auto q = *p; q != *p + 4; ++q) {	
		std::cout << *q << ' ';
	}
	std::cout << std::endl;
}

// 使用decltype
decltype(ia) p;	// p是一个int[3][4]

可以使用标准库函数 beginend 来简化指针运算:

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

还可以使用类型别名来简化多维数组的指针:

using int_arr = int[4];	// 声明int_arr为int[4]的别名
// 等价于:
typedef int int_arr[4];

for (int_arr *p = ia; p != ia + 3; ++p) {
	for (int *q = *p; q != *p + 4; ++q) {
		std::cout << *q << '\t';
	}
	std::cout << std::endl;
}


好好学习天天向上~(๑•̀ㅂ•́)و✧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值