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

本文详细介绍了C++11中新增的范围for循环的使用方法,包括基本语法、复杂容器的处理及如何自定义类以支持迭代。

声明:本文少量代码转载自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++终于知道把这个重要功能加进语法中了。这个功能实在不知道该怎么翻译,语文没有学到家。


基本语法


[cpp]  view plain copy
  1. for ( range_declaration : range_expression) loop_statement        

比如说:

[cpp]  view plain copy
  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语句来简化类型声明


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


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

[cpp]  view plain copy
  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循环一样。


深入分析

[cpp]  view plain copy
  1. for ( range_declaration : range_expression) loop_statement        

“等价于”

[cpp]  view plain copy
  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. 迭代器本身支持* ++ !=运算符,既可以是成员函数,也可以是非成员函数。
比如说下面这个类:


[cpp]  view plain copy
  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支持* != ++运算符。
你遇到的编译错误: ``` [Error] range-based-for loops are not allowed in C++98 mode ``` 意思是:**你使用了 C++11 及以上标准才支持的范围 for 循环(range-based for loop),但你的编译器被设置为 C++98 模式,不支持这个特性。** --- ## ✅ 错误原因分析 ### ❌ 使用了范围 for 循环语法(C++11 特性) ```cpp std::vector<int> nums = {1, 2, 3, 4, 5}; for (int num : nums) { // ←← 这是 C++11range-based for std::cout << num << " "; } ``` 这段代码在 C++98/03 标准下是不被允许的。 --- ## ✅ 解决方案一:启用 C++11 或更高标准 你可以通过在编译时指定标准版本来启用 C++11 支持。 ### ✔ 使用 g++ 编译器时添加 `-std=c++11` 参数: ```bash g++ -std=c++11 -o myprogram main.cpp ``` 如果你用的是较新的标准(如 C++14、C++17)也可以写成: ```bash g++ -std=c++14 -o myprogram main.cpp g++ -std=c++17 -o myprogram main.cpp ``` 这样就可以继续使用现代 C++range-based for 循环。 --- ## ✅ 解决方案二:改用传统的 for 循环(适用于 C++98) 如果你不能更改编译器标准(比如因为项目限制或旧环境),可以将 range-based for 替换为传统写法: ### 示例:使用迭代器遍历 vector ```cpp #include <iostream> #include <vector> int main() { std::vector<int> nums = {1, 2, 3, 4, 5}; for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) { std::cout << *it << " "; } return 0; } ``` ### 示例:使用数组索引方式(不推荐,除非必须) ```cpp for (size_t i = 0; i < nums.size(); ++i) { std::cout << nums[i] << " "; } ``` --- ## ✅ 示例对比 | 写法 | 是否需要 C++11 | |------|----------------| | `for (int x : vec)` | ✅ 需要 C++11 | | `for (it = vec.begin(); it != vec.end(); ++it)` | ❌ 不需要 | | `for (int i = 0; i < vec.size(); ++i)` | ❌ 不需要 | --- ## ✅ 总结 | 错误信息 | 原因 | 解决方法 | |----------|------|-----------| | `range-based-for loops are not allowed in C++98 mode` | 使用了 C++11 的范围 for 循环,但编译器未启用 C++11 | 1. 编译时加上 `-std=c++11`<br>2. 使用传统 for + iterator 替代 | ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kaitiren

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值