C++ for循环 纯指针遍历多维数组

        指针是C/C++中很重要的一个概念,对指针操作熟悉的人,一般对程序对内存的访问和使用都比较敏感,多了解底层是很有益处的。一直都使用下标(subscript)来访问数组。一起来尝试用指针吧 !

        以二维数组的访问为例,直接给出代码:


#include 
using namespace std;

int main() {
	int ia[3][4] = {};
	/*
	error codes
	for(int **p1 = ia ; p1 != ia + 3 ; p1 ++)
	{
		for(int *p2 = *p1 ; p2 != *p1 + 4 ; p2 ++)
		{
			cout << *p2 << endl;
		}
	}
	*/
	
	//correct codes, define p1 as a pointer to array of four ints
	//once time
	for(int (*p1)[4]  = ia ; p1 != ia + 3 ; p1 ++)
	{
		for(int *p2 = *p1 ; p2 != *p1 + 4 ; p2 ++)
		{
			cout << *p2 << endl;
		}
	}
	return 0;
}


上面写了两份访问方式,第一份有问题,编译的时候,报错如下:




        上面说的是,不能把 int[ ] [ ]类型赋给 int **类型。但是由于C++规定 array 是不能直接赋值的,所以我们也不能把 p1 的类型改为 int [ ] [ ]。那咋办呢 ?

        根据C++对 array 的定义,多维数组本质上是 array of arrays,因此,二维数组 int [3][4] 相当于就是一个一维数组,只是它的每个元素都是一个长度为4的一维数组罢了。因此,对于 p1,我们只要把它定义为一个指向 “长度为4的一维数组” 的指针即可。具体定义的格式,在第二份访问方式也就是正确的那个方式,可以看到。如果还是不是很懂数组的指针的定义方式,就请自行查阅 参考文献[1]吧。

        对于纯指针访问三维以上的多维数组的方法,以此类推就行了。


另附干货,二维数组的9种访问方法,先从编程形式上统分为三个大类:(其实还有引用,正在补充当中,就有四种了

1. 用 range for 访问 2. 用 指针访问 3. 用下标 访问   (其实这三种方法本质上都是使用指针访问的,range for 本质上是使用了iterator,而iterator实质上就是指针。下标呢就是指针加偏移,所以也是通过指针


然后,每个大类里面又细分为三个小类:1. 迭代变量精确到类型 2. 迭代变量类型用auto 3. 迭代变量类型用decltype

代码如下所示:

#include 
#include 
using namespace std;

int main() {

	int ia[3][4] = {};

	/*---------access with ranger for ----------*/

	/* range for and precise type */
	for(int (&row)[4] : ia)
	{
		for( int col : row)
			cout << col << " ";
		cout << endl;
	}

	cout << endl;

	/* range for and auto */
	for(auto &row : ia)
	{
		for(auto col : row)
			cout << col << " ";
		cout << endl;
	}

	cout << endl;	

	/* range for and decltype */
	for(decltype(ia[0]) row : ia)
	{
		for(decltype(ia[0][0]) col : row)
			cout << col << " ";
		cout << endl;
	}

	cout << endl;

	/*---------access with pointer----------*/

	/* pointer and precise type */
	for(int (*p1)[4] = ia ; p1 != ia + 3 ; p1 ++)
	{
		for(int *p2 = *p1 ; p2 != *p1 + 4 ; p2 ++)
			cout << *p2 << " ";
		cout << endl;
	}

	cout << endl;

	/* pointer and auto */
	for(auto row = ia ; row != ia + 3 ; row ++)
	{
		for(auto col = *row ; col != *row + 4 ; col ++)
			cout << *col << " ";
		cout << endl;
				
	}

	cout << endl;

	/* pointer and decltype */
	for(decltype(&ia[0]) p1 = ia; p1 != ia + 3 ; p1 ++)
	{
		for(decltype(&ia[0][0]) p2 = *p1; p2 != *p1+4 ; p2 ++)
			cout << *p2 << " ";
		cout << endl;
	}

	cout << endl;	

	/*---------access with subscript----------*/

	/* subscript and precise type */
	for(int i = 0 ; i < 3 ; i ++)
	{
		for(int j = 0 ; j < 4 ; j ++)
			cout << ia[i][j] << " ";
		cout << endl;
	}

	cout << endl;

	/* subscript and auto */
	for(auto i = 0 ; i < 3 ; i ++)
	{
		for(auto j = 0 ; j < 4 ; j ++)
			cout << ia[i][j] << " ";
		cout << endl;
	}

	cout << endl;

	/* subscript and decltype */
	for(decltype(0) i = 0 ; i < 3 ; i ++) 
	{
		for(decltype(0) j = 0 ; j < 4 ; j ++)
			cout << ia[i][j] << " ";
		cout << endl;
	}
	return 0;
}


References

[1] 《C++ Primer Fifth Edition》  Stanley B. Lippman, Josée Lajoie, Barbara E. Moo

[2]   C++11 range for 遍历多维数组, 迭代变量添加引用 "&"的问题

你可能感兴趣的:(C++)