设为首页 加入收藏

TOP

3.6 多维数组(2)
2013-10-07 16:28:08 来源: 作者: 【 】 浏览:101
Tags:3.6 多维

3.6  多维数组(2)

这个循环赋给ia元素的值和之前那个循环是完全相同的,区别之处是通过使用范围for语句把管理数组索引的任务交给了系统来完成。因为要改变元素的值,所以得把控制变量row和col声明成引用类型(参见3.2.3节,第93页)。第一个for循环遍历ia的所有元素,这些元素是大小为4的数组,因此row的类型就应该是含有4个整数的数组的引用。第二个for循环遍历那些4元素数组中的某一个,因此col的类型是整数的引用。每次迭代把cnt的值赋给ia的当前元素,然后将cnt加1。

在上面的例子中,因为要改变数组元素的值,所以我们选用引用类型作为循环控制变量,但其实还有一个深层次的原因促使我们这么做。举一个例子,考虑如下的循环:

  1. for (const auto &row : ia)  //对于外层数组的每一个元素  
  2.     for (auto col : row)    //对于内层数组的每一个元素  
  3.         cout << col << endl;  

这个循环中并没有任何写操作,可是我们还是将外层循环的控制变量声明成了引用类型,这是为了避免数组被自动转成指针(参见3.5.3节,第117页)。假设不用引用类型,则循环如下述形式:

  1. for (auto row : ia)  
  2.     for (auto col : row)  

程序将无法通过编译。这是因为,像之前一样第一个循环遍历ia的所有元素,注意这些元素实际上是大小为4的数组。因为row不是引用类型,所以编译器初始化row时会自动将这些数组形式的元素(和其他类型的数组一样)转换成指向该数组内首元素的指针。这样得到的row的类型就是int*,显然内层的循环就不合法了,编译器将试图在一个int*内遍历,这显然和程序的初衷相去甚远。

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

指针和多维数组

当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针。

定义指向多维数组的指针时,千万别忘了这个多维数组实际上是数组的数组。

因为多维数组实际上是数组的数组,所以由多维数组名转换得来的指针实际上是指向第一个内层数组的指针:

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

根据3.5.1节(第115页)提出的策略,我们首先明确(*p)意味着p是一个指针。接着观察右边发现,指针p所指的是一个维度为4的数组;再观察左边知道,数组中的元素是整数。因此,p就是指向含有4个整数的数组的指针。

在上述声明中,圆括号必不可少:
 

  1. int *ip[4];     // 整型指针的数组  
  2.     int (*ip)[4];   // 指向含有4个整数的数组  

随着C++(www.cppentry.com)11新标准的提出,通过使用auto或者decltype(参见2.5.2节,第68页)就能尽可能地避免在数组前面加上一个指针类型了:
 

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

外层的for循环首先声明一个指针p并令其指向ia的第一个内层数组,然后依次迭代直到ia的全部3行都处理完为止。其中递增运算++p负责将指针p移动到ia的下一行。

内层的for循环负责输出内层数组所包含的值。它首先令指针q指向p当前所在行的第一个元素。*p是一个含有4个整数的数组,像往常一样,数组名被自动地转换成指向该数组首元素的指针。内层for循环不断迭代直到我们处理完了当前内层数组的所有元素为止。为了获取内层for循环的终止条件,再一次解引用p得到指向内层数组首元素的指针,给它加上4就得到了终止条件。

当然,使用标准库函数begin和end(参见3.5.3节,第118页)也能实现同样的功能,而且看起来更简洁一些:

  1. // p指向ia的第一个数组  
  2.         for (auto p = begin(ia); p != end(ia); ++p) {  
  3.             // q指向内层数组的首元素  
  4.             for (auto q = begin(*p); q != end(*p); ++q)  
  5.                 cout << *q << ’ ’; // 输出q所指的整数值  
  6.         cout << endl;  
  7.     }  

在这一版本的程序中,循环终止条件由end函数负责判断。虽然我们也能推断出p的类型是指向含有4个整数的数组的指针,q的类型是指向整数的指针,但是使用auto关键字我们就不必再烦心这些类型到底是什么了。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇3.6 多维数组(1) 下一篇3.6 多维数组(3)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: