现在的位置: 首页 > 综合 > 正文

C++11 新特性之Range-based for loops

2019年08月24日 ⁄ 综合 ⁄ 共 3222字 ⁄ 字号 评论关闭

声明:本文少量代码转载自Alex Allain的文章 http://www.cprogramming.com/c++11/c++11-ranged-for-loop.html

转载请注明出处:http://blog.csdn.net/srzhz/article/details/7952723

很多语言都有Range-based for loops这个功能,现在C++终于知道把这个重要功能加进语法中了。这个功能实在不知道该怎么翻译,语文没有学到家。

基本语法

  1. for ( range_declaration : range_expression) loop_statement        

比如说:

  1. vector<int> vec;  
  2. vec.push_back( 1 );  
  3. vec.push_back( 2 );  
  4.    
  5. for (int i : vec )  
  6. {  
  7.     cout << i;  
  8. }  

for语言这么写可以很方便地遍历vector这类的容器。具体什么样的东西可以遍历呢?这个留在后面说。

对于比较复杂的容器可以用auto语句来简化类型声明

  1. map<string, string> complexVector;  
  2. for ( auto complexVectorEntry : complexVector )  
  3. {  
  4.             cout << complexVectorEntry.first << " < " << complexVectorEntry.second << ">" << endl;  
  5. }   



这两个例子中都没有修改遍历元素的值。如果你要想修改它们的值,请使用引用类型

  1. vector<int> vec;  
  2. vec.push_back( 1 );  
  3. vec.push_back( 2 );  
  4.    
  5. for (auto& i : vec )  
  6. {  
  7.    i++;  
  8. }  

请注意,你依然可以用continue语句来开始下一次迭代,使用break跳出循环。这一点和普通的for循环一样。


深入分析

  1. for ( range_declaration : range_expression) loop_statement        


“等价于”

  1. {  
  2.     auto && __range = range_expression ;   
  3.     auto __begin = begin_expr(__range);   
  4.     auto __end = end_expr(__range);   
  5.     for (;__begin != __end; ++__begin) {  
  6.         range_declaration = *__begin;   
  7.         loop_statement   
  8.     }   
  9. }  



请注意,“等价于”并不表示编译器就是这么实现range-based for loops的。只是说两者的运行效果等价

上面最重要的就是 begin_expr 和 end_expr 的定义如下:

  1. 对于数组类型 begin_expr和end_expr分别等于(__range)(__range + __bound)
  2. 对于STL中的容器,两者分别等于__range.begin()和__range.end()
  3. 对于其他类型,两者分别等于begin(__range)和end(__range)。编译器将会通过参数类型来找到合适的begin和end函数

让自定义的类可以迭代

通过ranged-based for loops的等价语句可以看出,可以知道只要符合一定的要求,那么自己定义的类也可以放在ranged-based for loops中进行迭代。事实上要想进行迭代,一个类需要满足以下条件:
  1. begin函数和end函数,作用是分别指向第一个数据和最后一个数据。返回值是一个可以自己定义的迭代器。既可以是成员函数,也可以是非成员函数。
  2. 迭代器本身支持* ++ !=运算符,既可以是成员函数,也可以是非成员函数。
比如说下面这个类:
  1. #include <iostream>  
  2.    
  3. using namespace std;  
  4.    
  5.   
  6. class IntVector;  
  7.    
  8. class Iter  
  9. {  
  10.     public:  
  11.     Iter (const IntVector* p_vec, int pos)  
  12.         : _pos( pos )  
  13.         , _p_vec( p_vec )  
  14.     { }  
  15.    
  16.     // these three methods form the basis of an iterator for use with  
  17.     // a range-based for loop  
  18.     bool  
  19.     operator!= (const Iter& other) const  
  20.     {  
  21.         return _pos != other._pos;  
  22.     }  
  23.    
  24.     // this method must be defined after the definition of IntVector  
  25.     // since it needs to use it  
  26.     int operator* () const;  
  27.    
  28.     const Iter& operator++ ()  
  29.     {  
  30.         ++_pos;  
  31.         return *this;  
  32.     }  
  33.    
  34.     private:  
  35.     int _pos;  
  36.     const IntVector *_p_vec;  
  37. };  
  38.    
  39. class IntVector  
  40. {  
  41.     public:  
  42.     IntVector ()  
  43.     {  
  44.     }  
  45.    
  46.     int get (int col) const  
  47.     {  
  48.         return _data[ col ];  
  49.     }  
  50.     Iter begin () const  
  51.     {  
  52.         return Iter( this, 0 );  
  53.     }  
  54.    
  55.     Iter end () const  
  56.     {  
  57.         return Iter( this, 100 );  
  58.     }  
  59.    
  60.     void set (int index, int val)  
  61.     {  
  62.         _data[ index ] = val;  
  63.     }  
  64.    
  65.     private:  
  66.    int _data[ 100 ];  
  67. };  
  68.    
  69. int  
  70. Iter::operator* () const  
  71. {  
  72.      return _p_vec->get( _pos );  
  73. }  
  74.    
  75.   
  76. int main()  
  77. {  
  78.     IntVector v;  
  79.     for ( int i = 0; i < 100; i++ )  
  80.     {  
  81.         v.set( i , i );  
  82.     }  
  83.     for ( int i : v ) { cout << i << endl; }  
  84. }  
IntVector就是一个想要进行迭代的类。它的being和end函数返回一个迭代器Iter。而Iter支持* != ++运算符。

抱歉!评论已关闭.