范围 for 语句与二维数组

来源:互联网 发布:淘宝的周期怎么算 编辑:程序博客网 时间:2024/04/28 14:14

我的主力博客:半亩方塘


为了讲清楚我们要说明的问题,首先我们来定义一个二维数组:

int ival[2][3] = {    {1, 2, 3},    {4, 5, 6}};  

这是一个2行3列的二维数组,如果我们要使用范围 for 循环来输出这个二维数组中的元素的话,相应地代码如下:

for (auto &row : ival) {    for (auto elem : row)        cout << elem << " ";    cout << endl;}  

上面的代码能不能完成预期的输出二维数组元素的功能呢?我们来实际运行一下,在 VS2013 中的代码如下:



运行结果如下:




显然,实现了我们预期的目的,但是这里有一个问题,为什么要在最外层的范围 for 循环使用 & 操作符呢?写成for (auto row : ival) 不行么?当然是不行的,下面就来交待一下理由。

我们不妨将 for (auto &row : ival) 改写成传统的 for 循环试试:

for (auto mbeg = begin(ival), mend = end(ival);    mbeg != mend; ++mbeg)    auto &row = *mbeg;

在 VS2013 中运行一下看看改写的是否正确:



运行结果如下:




显然我们改写的是对的,实际上,范围 for 循环本质上就是我们改写的传统 for 循环,下面就我们改写后的传统 for 循环来分析一下:

begin(ival) 得到的是指向 ival 首元素的指针,ival 的首元素是什么呢?二维数组本质上是数组的数组,所以我们得到的是一个指向含有 3 个元素的一维数组的指针,指向数组的指针实际上是指向数组首元素的指针的指针(见我的博文: 指向数组的指针与指向数组首元素的指针 ),因此我们对 mbeg 解引用之后将会得到一个指向某个一维数组首元素的指针,相当于一个一维数组的数组名,如果没有 & 操作符,即如果是以下的形式:

auto row = *mbeg;

row 的类型将会是 int*,即 row 是一个整型指针的副本,接下来的范围 for 语句就成了遍历一个指针内的元素了,这显然是错误的,与我们的初衷大相径庭,但是如果我们加上一个引用操作符( & ),对 mbeg 解引用之后得到的指针相当于一个一维数组的数组名,因此 row 的类型就变成了 int (&row)[3],即 row 是与一个含有 3 个整型数的一维数组绑定的引用,接下来的范围 for 语句就是遍历这个含有 3 个整型数的一维数组,这与我们的初衷是相符的,实际上:

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

编译原理的知识告诉我们, 指针的类型包括指针所指向的类型 ,因此,指向数组的指针与指向数组首元素的指针是不同类型的指针,指向数组首元素的指针与指向一个普通元素的指针也属于不同类型的指针,这是编译方面的知识,适当了解一下有助于我们理解相关的语言特性。


还有一个极易混淆的地方需要特别指出一下,在我们处理 initializer_list 类型的元素的时候,通常也会用到 & 操作符:

// 打印 list 中的元素void print (initializer_list<string> list){    for (const auto &elem : list)        cout << elem << " ";    cout << endl;}  

这里的范围 for 语句为什么要用到引用操作符呢?实际上,不用引用操作符也是可以的,也就是说,这里的范围 for 语句可以写成如下的形式:

for (const auto elem : list)

这样最后仍然能够得到一样的结果,这里使用 & 操作符主要是为了避免存储空间的浪费和拷贝造成的时间效率低下而直接将 elem 绑定到一个 const string 类型的对象上(initializer_list 类型的对象里面的元素都是常量),如果不使用 & 操作符的话, elem 将是 list 里面元素的拷贝,造成了存储空间的浪费,下面将程序在 VS2013 中运行一下以验证上面的想法。

加了 & 操作符的情形:


运行结果如下:


未加 & 操作符的情形:


运行结果如下:


完全符合预期的想法。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 智能锁电机坏了怎么办 注塑机加热嘴内扣突了怎么办 tpu粘在螺杆上怎么办 注塑机锁模时会有射退动作怎么办 电动车刹车油泵不打油怎么办 cad转pdf颜色浅怎么办 松下多功能传真一体机卡纸怎么办 无刷电机坏了怎么办 6kv高压电机绝缘不合格怎么办? 400t油压机下降太慢怎么办 无法连线到服务器1~1怎么办? 数控车床车角度不亮怎么办 超市存包柜的票不见了怎么办 交货期来不及导致船期延误怎么办 跑1000米中途累怎么办 手指被机器压烂怎么办 机械手不能回归原点该怎么办 前缘送纸纸板翘怎么办 三菱AL 1R.2报警怎么办 工作好但领导不好伺候怎么办 孕妇憋尿憋的小腹疼怎么办 怀孕憋尿憋的小腹疼怎么办 半夜憋尿憋的小腹疼怎么办 新生儿大便次数较多怎么办 母猎生下三天没有奶怎么办 孩孑大便干不爱喝水怎么办 发那科1050报警怎么办 plc模块bf亮了怎么办 plc模块df亮了怎么办 西门子触摸屏进不了主画面怎么办 pos机显示白屏怎么办 洗衣机的门坏了怎么办 西门子洗衣机门坏了怎么办 拆线线断在肉里怎么办 总线绝对值编码器方向反了怎么办 台达伺服报警009怎么办 台达plc禁止上传怎么办? 潜水泵电机启动绕组断线了怎么办? 永磁电机磁没了怎么办 热水器热水管坏了怎么办 松下伺服驱动器坏了怎么办