您的位置:首页 > 编程语言 > C语言/C++

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

2014-03-27 17:07 417 查看
声明:本文少量代码转载自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
plaincopy

for ( range_declaration : range_expression) loop_statement

比如说:

[cpp] view
plaincopy

vector<int> vec;

vec.push_back( 1 );

vec.push_back( 2 );



for (int i : vec )

{

cout << i;

}

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

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

[cpp] view
plaincopy

map<string, string> complexVector;

for ( auto complexVectorEntry : complexVector )

{

cout << complexVectorEntry.first << " < " << complexVectorEntry.second << ">" << endl;

}

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

[cpp] view
plaincopy

vector<int> vec;

vec.push_back( 1 );

vec.push_back( 2 );



for (auto& i : vec )

{

i++;

}

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



深入分析

[cpp] view
plaincopy

for ( range_declaration : range_expression) loop_statement

“等价于”

[cpp] view
plaincopy

{

auto && __range = range_expression ;

auto __begin = begin_expr(__range);

auto __end = end_expr(__range);

for (;__begin != __end; ++__begin) {

range_declaration = *__begin;

loop_statement

}

}

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

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

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

让自定义的类可以迭代

通过ranged-based for loops的等价语句可以看出,可以知道只要符合一定的要求,那么自己定义的类也可以放在ranged-based for loops中进行迭代。事实上要想进行迭代,一个类需要满足以下条件:

begin函数和end函数,作用是分别指向第一个数据和最后一个数据。返回值是一个可以自己定义的迭代器。既可以是成员函数,也可以是非成员函数。
迭代器本身支持* ++ !=运算符,既可以是成员函数,也可以是非成员函数。

比如说下面这个类:

[cpp] view
plaincopy

#include <iostream>



using namespace std;





class IntVector;



class Iter

{

public:

Iter (const IntVector* p_vec, int pos)

: _pos( pos )

, _p_vec( p_vec )

{ }



// these three methods form the basis of an iterator for use with

// a range-based for loop

bool

operator!= (const Iter& other) const

{

return _pos != other._pos;

}



// this method must be defined after the definition of IntVector

// since it needs to use it

int operator* () const;



const Iter& operator++ ()

{

++_pos;

return *this;

}



private:

int _pos;

const IntVector *_p_vec;

};



class IntVector

{

public:

IntVector ()

{

}



int get (int col) const

{

return _data[ col ];

}

Iter begin () const

{

return Iter( this, 0 );

}



Iter end () const

{

return Iter( this, 100 );

}



void set (int index, int val)

{

_data[ index ] = val;

}



private:

int _data[ 100 ];

};



int

Iter::operator* () const

{

return _p_vec->get( _pos );

}





int main()

{

IntVector v;

for ( int i = 0; i < 100; i++ )

{

v.set( i , i );

}

for ( int i : v ) { cout << i << endl; }

}

IntVector就是一个想要进行迭代的类。它的being和end函数返回一个迭代器Iter。而Iter支持* != ++运算符。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: