很多語言都有Range-based for loops這個功能,現在C++終於知道把這個重要功能加進語法中了。這個功能實在不知道該怎麼翻譯,語文沒有學到家。
基本語法
[cpp]
for ( range_declaration : range_expression) loop_statement
比如說:
[cpp]
vector<int> vec;
vec.push_back( 1 );
vec.push_back( 2 );
for (int i : vec )
{
cout << i;
}
for語言這麼寫可以很方便地遍歷vector這類的容器。具體什麼樣的東西可以遍歷呢?這個留在後面說。
對於比較復雜的容器可以用auto語句來簡化類型聲明
[cpp]
map<string, string> complexVector;
for ( auto complexVectorEntry : complexVector )
{
cout << complexVectorEntry.first << " < " << complexVectorEntry.second << ">" << endl;
}
這兩個例子中都沒有修改遍歷元素的值。如果你要想修改它們的值,請使用引用類型
[cpp]
vector<int> vec;
vec.push_back( 1 );
vec.push_back( 2 );
for (auto& i : vec )
{
i++;
}
請注意,你依然可以用continue語句來開始下一次迭代,使用break跳出循環。這一點和普通的for循環一樣。
深入分析
[cpp]
for ( range_declaration : range_expression) loop_statement
“等價於”
[cpp]
{
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]
#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()
{ www.2cto.com
IntVector v;
for ( int i = 0; i < 100; i++ )
{
v.set( i , i );
}
for ( int i : v ) { cout << i << endl; }
}