今天在阅读《c++ primer fifth edition》中多维数组一节时,写一段遍历二维数组中元素的程序时,对于以前关于数组与指针的一些模糊点有了一些较为清晰的理解,将其记录下来,程序很简单,就是遍历输出二维数组中的元素:
1.以前对二维数组的遍历,本人全部都是定义i,j两个变量,一个控制外层,一个控制内层:
1 for(int i = 0; i < 3; i++) 2 { 3 for(int j = 0; j < 4; j++) 4 cout << a[i][j] << " "; 5 cout << endl; 6 }2.c++中二维数组,其实是一维数组,只是其中的每个元素又是一个数组,因此我们可以这样写:
1 for(int (*i)[4] = a; i != a + 3; i++) //i是指向数组的指针,数组中含有4个整型变量 2 { 3 for(int *j = *i; j != *i + 4; j++) //*i得到的是指向数组中首元素的指针! 4 cout << *j << " "; 5 cout << endl; 6 }
注意 int (*i)[4]表示指向含有四个整型元素的数组的指针,从内层向外层去读,首先是一个指针
int* i[4] 表示含有四个整型指针的数组,从右向左去读
问题所在 :
起初对于 int *j = *i;不能理解,以为i是指向数组的指针,当然指向数组中的首元素,而解引用*i显然应该是数组中的首元素了,那怎么又赋值给一个指针了呢?
从网上查了一些资料才发现, *i原来也表示指向数组首元素的指针。
进行了一些测试,测试程序如下:
1 int ia[2][3] = {{1,2,3}, {4,5,6}}; 2 int (*pia)[3] = ia; 3 cout << "pia = " << pia << endl; //指向数组的指针 4 cout << "*pia = " << *pia << endl; //对指向数组的指针解引用得到指向数组中首元素的指针 5 cout << "pia + 1 = " << pia + 1 << endl; 6 cout << "*pia + 1 = " << *pia + 1 << endl;
结果如下:
显然pia 和 *pia的输出正是上面说的情况,而对于pia+1和*pia+1就容易理解了,pia是指向数组的指针, 可以将其“1个单位”(也就是+1)理解成整个指向的数组大小 ,而*pia相当于“进入到了指向的数组内”, 其“1个单位”显然应该是数组中一个元素。
3.通过范围for(range for)遍历二维数组
1 for(const int (&i)[4] : a) 2 { 3 for(int ii: i) 4 cout << ii << " "; 5 cout << endl; 6 } 7 cout << "------------------------------" << endl; 8 9 for(const auto & i : a) 10 { 11 for(auto ii : i) 12 cout << ii << " "; 13 cout << endl; 14 }
范围for是c++11新增加的遍历整个序列的一种简单手段,可以实现对下标的自动管理,无需程序员手动管理,由此看来对于遍历整个序列可以,而需要遍历部分序列就不方便了,毕竟下标的管理是不透明的
需要说明的一点是,在外层遍历中,每个元素的类型是引用,而非普通指针类型,因为如果是指针类型的话,在内层循环的时候,遍历的序列就成了指针了,是不行的,而将元素声明称数组的引用类型则可。
4.使用类型别名来简化
1 using int_array = int[4]; 2 for(int_array *i = a; i != a+3; ++i) 3 { 4 for(int *j = *i; j != *i + 4; ++j) 5 cout << *j << " "; 6 cout << endl; 7 }
后面三种方法,其实都是相同的原理,都是利用了二维数组是“由数组组成的数组”这一规则,关键是一些细节上的理解,尤其是涉及到了指针,更是需要小心翼翼。
同时,反思自己,今后遇到模棱两可的问题,千万不能放过,一定要多多查询资料, 至能够说服自己 。
一些错误之处,请各位指出,虚心学习。