0. 形式

for ( declaration : expression ) statement

0.1 根据标准将会扩展成这样的形式:

1   {
2     auto&& __range = expression;
3     for (auto __begin = begin-expression,
4               __end = end-expression;
5          __begin != __end;
6          ++__begin)
7     {
8       declaration = *__begin;
9       statement
10    }
11  }


0.1.1  行3,4 ,begin 和 end 的判断规则:

The begin-expression and end-expression (lines 3 and 4) are determined as follows:

  • A. If expression is an array, then begin-expression and end-expressionare __range and __range + __bound, respectively, where __bound is the array bound.
  • B. If expression is of a class type that declares begin() and end()member functions, then begin-expression and end-expression are__range.begin() and __range.end(), respectively.
  • C. Otherwise, begin-expression and end-expression are begin(__range)and end(__range), respectively, where the begin() and end()functions are looked up using the argument-dependent lookup (ADL) which also includes the std namespace.

With arrays taken care of by the first rule, the second rule makes sure that all the standard containers as well as all the user-defined ones that follow the standard sequence interface will work with range-based for out of the box. For example, in ODB (an ORM for C++), we have the container-like result class template which allows iteration over the query result. Because it has the standard sequence interface with a forward iterator, we didn’t have to do anything extra to make it work with range-based for.

The last rule (the fallback to the free-standing begin()and end()functions) allows us to non-invasively adapt an existing container to the range-based for loop interface.

0.2 类型推断

std::vector<int> v = {1, 2, 3, 5, 7, 11};
const std::vector<int> cv = {1, 2, 3, 5, 7, 11};
 
for (auto x: v) // x is int
  ...;
 
for (auto x: cv) // x is int
  ...;
 
for (auto& x: v) // x is int&
  ...;
 
for (auto& x: cv) // x is const int&

1.  例子

  1. #include <iostream>
  2. #include <vector>
  3. int main ()
  4. {
  5. std::vector<int> data = { 1, 2, 3, 4 };
  6. for ( int datum : data )
  7. {
  8. std::cout << datum << std::endl;
  9. }
  10. }
  1. /*output
  2. 1
  3. 2
  4. 3
  5. 4
  6. */



2.  性能上的考虑
2.1 每次循环会创建一份 a 的拷贝

for(autoa : a_vec)
{
}


2.2 避免拷贝

for(constauto&a : a_vec)
{
}



3. 一个实现了 container semantics 的例子:

3.1 simple iterator

  1. #include <iostream>
  2. using namespace std;
  3. // forward-declaration to allow use in Iter
  4. class IntVector;
  5. class Iter
  6. {
  7. public:
  8. Iter(const IntVector* p_vec, int pos)
  9. : _pos(pos)
  10. , _p_vec(p_vec)
  11. { }
  12. // these three methods form the basis of an iterator for use with
  13. // a range-based for loop
  14. bool
  15. operator!= (const Iter& other) const
  16. {
  17. return _pos != other._pos;
  18. }
  19. // this method must be defined after the definition of IntVector
  20. // since it needs to use it
  21. int operator* () const;
  22. const Iter& operator++ ()
  23. {
  24. ++_pos;
  25. // although not strictly necessary for a range-based for loop
  26. // following the normal convention of returning a value from
  27. // operator++ is a good idea.
  28. return *this;
  29. }
  30. private:
  31. int _pos;
  32. const IntVector *_p_vec;
  33. };
  34. class IntVector
  35. {
  36. public:
  37. IntVector()
  38. {
  39. }
  40. int get(int col) const
  41. {
  42. return _data[col];
  43. }
  44. Iter begin() const
  45. {
  46. return Iter(this, 0);
  47. }
  48. Iter end() const
  49. {
  50. return Iter(this, 100);
  51. }
  52. void set(int index, int val)
  53. {
  54. _data[index] = val;
  55. }
  56. private:
  57. int _data[100];
  58. };
  59. int
  60. Iter::operator* () const
  61. {
  62. return _p_vec->get(_pos);
  63. }
  64. // sample usage of the range-based for loop on IntVector
  65. int main()
  66. {
  67. IntVector v;
  68. for (int i = 0; i < 100; i++)
  69. {
  70. v.set(i, i);
  71. }
  72. for (int i : v) { cout << i << endl; }
  73. }

3.2 reverse iterator

template <typename T>
struct reverse_range
{
private:
  T& x_;
 
public:
  reverse_range (T& x): x_ (x) {}
 
  auto begin () const -> decltype (this->x_.rbegin ())
  {
    return x_.rbegin ();
  }
 
  auto end () const -> decltype (this->x_.rend ())
  {
    return x_.rend ();
  }
};
 
template <typename T>
reverse_range<T> reverse_iterate (T& x)
{
  return reverse_range<T> (x);
}
 
std::vector<int> v = {1, 2, 3, 5, 7, 11};
 
for (auto x: reverse_iterate (v))


4. 一个完整的例子 (编译出错,说找不到容器 begin end 实现)

  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <iterator>
  5. #include <algorithm>
  6. #include <unordered_map>
  7. template<classITERATOR>
  8. ITERATOR begin( std::pair<ITERATOR,ITERATOR> &range )
  9. {
  10. returnrange.first;
  11. }
  12. template<classITERATOR>
  13. ITERATOR end( std::pair<ITERATOR,ITERATOR> &range )
  14. {
  15. returnrange.second;
  16. }
  17. template<classT>
  18. std::istream_iterator<T> begin(std::istream_iterator<T> &ii_stream)
  19. {
  20. returnii_stream;
  21. }
  22. template<classT>
  23. std::istream_iterator<T> end(std::istream_iterator<T> &ii_stream)
  24. {
  25. returnstd::istream_iterator<T>();
  26. }
  27. intmain(intargc, char* argv[])
  28. {
  29. std::ifstream data( "sowpods.txt");
  30. std::unordered_map<std::string,int> counts;
  31. std::unordered_multimap<std::string,std::string> words;
  32. for( conststd::string &s : std::istream_iterator<std::string>( data ) )
  33. {
  34. std::string temp = s;
  35. std::sort(temp.begin(), temp.end() );
  36. counts[temp]++;
  37. words.insert( std::make_pair(temp,s) );
  38. }
  39. auto ii = std::max_element( counts.begin(),
  40. counts.end(),
  41. [](conststd::pair<std::string,int> &v1,
  42. conststd::pair<std::string,int> &v2)
  43. {
  44. returnv1.second < v2.second;
  45. }
  46. );
  47. std::cout << "The maximum anagram family has " << ii->second << " members:\n";
  48. for( constauto &map_entry : words.equal_range( ii->first ) )
  49. std::cout << map_entry.second << " ";
  50. std::cout << std::endl;
  51. return0;
  52. }

//z 2014-06-12 13:26:11 L.202'38029 BG57IV3@XCL T2508411853.K.F636940351 [T11,L175,R6,V152]
5. 一些 wrapper 或 iterator 例子

#include <memory>
#include <iterator> /* Only provides the bare minimum to support range-based for loops.
Since the internal iterator of a range-based for is inaccessible,
there is no point in more functionality here. */
template< typename iter >
struct range_iterator_reference_wrapper
: std::reference_wrapper< iter > {
iter &operator++() { return ++ this->get(); }
decltype( * std::declval< iter >() ) operator*() { return * this->get(); }
range_iterator_reference_wrapper( iter &in )
: std::reference_wrapper< iter >( in ) {}
friend bool operator!= ( range_iterator_reference_wrapper const &l,
range_iterator_reference_wrapper const &r )
{ return l.get() != r.get(); }
}; namespace unpolluted {
/* Cannot call unqualified free functions begin() and end() from
within a class with members begin() and end() without this hack. */
template< typename u >
auto b( u &c ) -> decltype( begin( c ) ) { return begin( c ); }
template< typename u >
auto e( u &c ) -> decltype( end( c ) ) { return end( c ); }
} template< typename iter >
struct range_proxy {
range_proxy( iter &in_first, iter in_last )
: first( in_first ), last( in_last ) {} template< typename T >
range_proxy( iter &out_first, T &in_container )
: first( out_first ),
last( unpolluted::e( in_container ) ) {
out_first = unpolluted::b( in_container );
} range_iterator_reference_wrapper< iter > begin() const
{ return first; }
range_iterator_reference_wrapper< iter > end()
{ return last; } iter &first;
iter last;
}; template< typename iter >
range_proxy< iter > visible_range( iter &in_first, iter in_last )
{ return range_proxy< iter >( in_first, in_last ); } template< typename iter, typename container >
range_proxy< iter > visible_range( iter &first, container &in_container )
{ return range_proxy< iter >( first, in_container ); }

Usage:

#include <vector>
#include <iostream>
std::vector< int > values{ 1, 3, 9 }; int main() {
// Either provide one iterator to see it through the whole container...
std::vector< int >::iterator i;
for ( auto &value : visible_range( i, values ) )
std::cout << "# " << i - values.begin() << " = " << ++ value << '\n'; // ... or two iterators to see the first incremented up to the second.
auto j = values.begin(), end = values.end();
for ( auto &value : visible_range( j, end ) )
std::cout << "# " << j - values.begin() << " = " << ++ value << '\n';
}


for(auto i : ForIterator(some_list)) {
// i is the iterator, which was returned by some_list.begin()
// might be useful for whatever reason
}

The implementation was not that difficult:

template <typename T> struct Iterator {
T& list;
typedef decltype(list.begin()) I; struct InnerIterator {
I i;
InnerIterator(I i) : i(i) {}
I operator * () { return i; }
I operator ++ () { return ++i; }
bool operator != (const InnerIterator& o) { return i != o.i; }
}; Iterator(T& list) : list(list) {}
InnerIterator begin() { return InnerIterator(list.begin()); }
InnerIterator end() { return InnerIterator(list.end()); }
};
template <typename T> Iterator<T> ForIterator(T& list) {
return Iterator<T>(list);
}

//z 2014-06-12 13:26:11 L.202'38029 BG57IV3@XCL T2508411853.K.F636940351 [T11,L175,R6,V152]
6. auto 部分的简单指导原则:
auto x : 使用拷贝
auto &x : 使用引用,指向原item,并且可能变更其值
const auto&x :指向原item,并且保证不改变其值

7. MAP 例子

Each element of the container is a map<K,
V>::value_type
, which is a typedef for std::pair<const
K, V>
. Consequently, you'd write this as

for (auto& kv : myMap) {
std::cout << kv.first << " has value " << kv.second << std::endl;
}

如前所述,为效率考虑,使用reference,如果不改变其值(如这里),还应该加上 const 。

8. 来自 ms 的例子

Executes statement repeatedly and sequentially for each element in expression.

 
 
for ( for-range-declaration : expression ) 
   statement

Remarks

 

Use the range-based for statement to construct loops that must execute through a "range", which is defined as anything that you can iterate through—for example, std::vector, or any other STL sequence whose range is defined by a begin() and end(). The name that is declared in the for-range-declaration portion is local to the for statement and cannot be re-declared in expression or statement. Note that the auto keyword is preferred in the for-range-declaration portion of the statement.

This code shows how to use ranged for loops to iterate through an array and a vector:

 
// range-based-for.cpp
// compile by using: cl /EHsc /nologo /W4
#include <iostream>
#include <vector>
using namespace std; int main()
{
// Basic 10-element integer array.
int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // Range-based for loop to iterate through the array.
for( int y : x ) { // Access by value using a copy declared as a specific type.
// Not preferred.
cout << y << " ";
}
cout << endl; // The auto keyword causes type inference to be used. Preferred. for( auto y : x ) { // Copy of 'x', almost always undesirable
cout << y << " ";
}
cout << endl; for( auto &y : x ) { // Type inference by reference.
// Observes and/or modifies in-place. Preferred when modify is needed.
cout << y << " ";
}
cout << endl; for( const auto &y : x ) { // Type inference by reference.
// Observes in-place. Preferred when no modify is needed.
cout << y << " ";
}
cout << endl;
cout << "end of integer array test" << endl;
cout << endl; // Create a vector object that contains 10 elements.
vector<double> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i + 0.14159);
} // Range-based for loop to iterate through the vector, observing in-place.
for( const auto &j : v ) {
cout << j << " ";
}
cout << endl;
cout << "end of vector test" << endl;
}

Here is the output:

1 2 3 4 5 6 7 8 9 10

1 2 3 4 5 6 7 8 9 10

1 2 3 4 5 6 7 8 9 10

1 2 3 4 5 6 7 8 9 10

end of integer array test

0.14159 1.14159 2.14159 3.14159 4.14159 5.14159 6.14159 7.14159 8.14159 9.14159

end of vector test

A range-based for loop terminates when one of these in statement is executed: a breakreturn, or goto to a labeled statement outside the range-based for loop. A continue statement in a range-based for loop terminates only the current iteration.

Keep in mind these facts about range-based for:

  • Automatically recognizes arrays.

  • Recognizes containers that have .begin() and .end().

  • Uses argument-dependent lookup begin() and end() for anything else.

c++11 : range-based for loop的更多相关文章

  1. c++11介绍

    C++11标准是 ISO/IEC 14882:2011 - Information technology -- Programming languages -- C++ 的简称[1]  . C++11 ...

  2. C++ 11标准

    C++11,也称为C++0x.为目前C++编程语言的最新正式标准(ISO/IEC 14882:2011).它将取代第二版标准ISO/IEC 14882:2003(第一版ISO/IEC 14882:19 ...

  3. C++进阶引导

    1.C++的用途和意义 t0185b047e29feffc26.jpg 总体来说,C++作为一门软件开发语言,它的流行度是在减少的.主要原因在于语言的复杂和灵活导致软件开发成本提高,这体现在开发周期和 ...

  4. C++ 如何进阶?

    1.C++的用途和意义 总体来说,C++作为一门软件开发语言,它的流行度是在减少的.主要原因在于语言的复杂和灵活导致软件开发成本提高,这体现在开发周期和人力上.它不适用于startup公司的快速开发, ...

  5. Bash For Loop Examples for Your Linux Shell Scripting--ref

    There are two types of bash for loops available. One using the “in” keyword with list of values, ano ...

  6. 在C++98基础上学习C++11新特性

    自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...

  7. 实验4 —— [bx]和loop的使用

    实验 综合使用 loop.[bx],编写完整汇编程序,实现向内存 b800:07b8 开始的连续 16 个字单元重复填充字数据 0403H. 以下为示例程序: assume cs:code # 1 c ...

  8. boost range

    1.Algorithms Boost.Range is library that, on the first sight, provides algorithms similar to those p ...

  9. 11.2.0.4 ORA-15025 ORA-27041 IBM AIX RISC System/6000 Error: 13: Permission denied

    ASM device error ORA-27041 ORA-15025 ORA-15081 (Doc ID 1487475.1) 描述总结:数据库的alert中发现大量ORA-27041 ORA-1 ...

  10. Sphinx 2.2.11-release reference manual

    1. Introduction 1.1. About 1.2. Sphinx features 1.3. Where to get Sphinx 1.4. License 1.5. Credits 1 ...

随机推荐

  1. Ajax原生XHR对象

    前端学了有一段时间了,在项目中我通常使用的都是jQuery封装好的Ajax函数($.ajax.$.get.$.post),使用非常的简单方便,但为了更清楚的了解Ajax,需要学习原生xhr对象.   ...

  2. swift和oc混编

    请参考这篇博客:点击查看

  3. 3.2:pandas数据的导入与导出【CSV,JSON】

    一:CSV数据 一]:导入数据 1)从CSV文件读入数据:pd.read_csv("文件名"),默认以逗号为分隔符 D:\data\ex1.csv文件内容:             ...

  4. 初学Java ssh之Spring 第一篇

    之前虽然毕业前实习的工作是使用的C# .NET语言,但是,毕业后还是果断应聘Java.虽然自己对Java的理解不如C#深入,只是对基础知识比较熟悉,但还是义无返顾了··· 虽然应聘经历比较坎坷,但最终 ...

  5. MS SQL到Oracle的数据迁移笔记

    MS SQL到Oracle的数据迁移笔记 一.任务背景 旧系统使用MS SQL Server数据库,新系统使用Oracle数据库,现在需要将旧系统中的数据迁移到新系统中,旧数据按照约定的规则转换后,能 ...

  6. C#构造函数使用

    作用:帮助我们初始化对像(给对像的每个属性依次的赋值) 构造函数是一个特殊的方法 1.构造函数没有返回值,连void也不能写 2.构造函数名称要和类名一样 3.创建对像时会执行构造函数 4.构造函数可 ...

  7. hdu5353

    模拟,,, 每个人有一些糖果,每两个人之间只能给一个糖果,问最后是否能让所有人的糖果数量相同,只要确定一个糖果的流向其他的就能够确定. 马虎了,卡了好几天,心塞塞的... #include<io ...

  8. Word 2010发布博客文章

    只测试了cnblog 1.新建文件选择word 2010自带的博客文章模板 2.在管理账户中新建一个博客账户,也就是你自己在博客园的账户,博客选其他 3.然后选择下一步,博客的URL在自己的博客设置里 ...

  9. Linux修改时间时区并在Tomcat中生效

    Linux查看当前时间时区linux:~ # datelinux:~ # date –Rlinux:~ # zdump -v /usr/share/zoneinfo/Asia/Beijing ---- ...

  10. PHP正则表达式屏蔽电话号码中间段

    要屏蔽电话号码中间段,首先要知道电话号码的正则表达式. 先来看看PHP匹配电话号码的正则表达式. 匹配固定电话的正则表达式为: /(0[0-9]{2,3}[\-]?[2-9][0-9]{6,7}[\- ...