读书频道 > 网站 > 网页设计 > 深入应用C++11:代码优化与工程级应用
1.4.1 for循环的新用法
15-07-07    下载编辑
收藏    我要投稿   
在StackOverflow的最近一次世界性调查中,C++11在所有的编程语言中排名第二, C++11受到程序员的追捧是毫不意外的,因为它就像C++之父Bjarne Stroustrup说的:它看起来就像一门新的语言。C++11新增加了相当多的立即去当当网订购

1.4 基于范围的for循环

在C++03/98中,不同的容器和数组,遍历的方法不尽相同,写法不统一,也不够简洁,而C++11基于范围的for循环以统一、简洁的方式来遍历容器和数组,用起来更方便了。

1.4.1 for循环的新用法

我们知道,在C++中遍历一个容器的方法一般是这样的:

#include <iostream>
#include <vector>

int main(void)
{
   std::vector<int> arr;

   // ...

   for(auto it = arr.begin(); it != arr.end(); ++it)
   {
      std::cout << *it << std::endl;
   }

   return 0;
}

上面借助前面介绍过的auto关键字,省略了迭代器的声明。

当然,熟悉stl的读者肯定还知道在<algorithm>中有一个for_each算法可以用来完成和上述同样的功能:

#include <algorithm>
#include <iostream>
#include <vector>

void do_cout(int n)
{
   std::cout << n << std::endl;
}

int main(void)
{
   std::vector<int> arr;
   // ...

   std::for_each(arr.begin(), arr.end(), do_cout);

   return 0;
}

std::for_each比起前面的for循环,最大的好处是不再需要关注迭代器(Iterator)的概念,只需要关心容器中的元素类型即可。

但不管是上述哪一种遍历方法,都必须显式给出容器的开头(Begin)和结尾(End)。这是因为上面的两种方法都不是基于“范围(Range)”来设计的。

我们先来看一段简单的C#代码:

int[] f?ibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in f?ibarray)
{
   System.Console.WriteLine(element);
}

上面这段代码通过“foreach”关键字使用了基于范围的for循环。可以看到,在这种for循环中,不再需要传递容器的两端,循环会自动以容器为范围展开,并且循环中也屏蔽掉了迭代器的遍历细节,直接抽取出容器中的元素进行运算。

与普通的for循环相比,基于范围的循环方式是“自明”的。这种语法构成的循环不需要额外的注释或语言基础,很容易就可以看清楚它想表达的意义。在实际项目中经常会遇到需要针对容器做遍历的情况,使用这种循环方式无疑会让编码和维护变得更加简便。

现在,在C++11中终于有了基于范围的for循环(The range-based for statement)。再来看一开始的vector遍历使用基于范围的for循环应该如何书写:

#include <iostream>
#include <vector>

int main(void)
{
   std::vector<int> arr = { 1, 2, 3 };

   // ...

   for(auto n : arr) // 使用基于范围的for循环
   {
      std::cout << n << std::endl;
   }

   return 0;
}

在上面的基于范围的for循环中,n表示arr中的一个元素,auto则是让编译器自动推导出n的类型。在这里,n的类型将被自动推导为vector中的元素类型int。

在n的定义之后,紧跟一个冒号(:),之后直接写上需要遍历的表达式,for循环将自动以表达式返回的容器为范围进行迭代。

在上面的例子中,我们使用auto自动推导了n的类型。当然在使用时也可以直接写上我们需要的类型:

std::vector<int> arr;
for(int n : arr) ;

基于范围的for循环,对于冒号前面的局部变量声明(for-range-declaration)只要求能够支持容器类型的隐式转换。因此,在使用时需要注意,像下面这样写也是可以通过编译的:

std::vector<int> arr;
for(char n : arr) ; // int会被隐式转换为char

在上面的例子中,我们都是在使用只读方式遍历容器。如果需要在遍历时修改容器中的值,则需要使用引用,代码如下:

for(auto& n : arr)
{
   std::cout << n++ << std::endl;
}

在完成上面的遍历后,arr中的每个元素都会被自加1。

当然,若只是希望遍历,而不希望修改,可以使用const auto&来定义n的类型。这样对于复制负担比较大的容器元素(比如一个std::vector<std::string>数组)也可以无损耗地进行遍历。

点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.3 功能
下一篇:1.5 小结
相关文章
图文推荐
JavaScript网页动画设
1.9 响应式
1.8 登陆页式
1.7 主题式
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站