C++11的for循環(huán),以及范圍Range類的簡單實現(xiàn)
C++11支持range-based for循環(huán)。這是一個很方便的特性,能省挺多代碼。以下代碼就能很方便的遍歷vector中的元素,并打印出來:
std::vector<int> int_vec; int_vec.push_back(1); int_vec.push_back(2); //如果要修改int_vec中的元素,將變量x聲明為 int& 即可 for (int x: int_vec) { std::cout << x << endl; }
可以遍歷的對象包括:
•數(shù)組。(不包括指針)
•定義了begin()和end()方法,且返回該方法返回迭代器的類對象。(STL 中所有容器都可以)
(對于動態(tài)生成的數(shù)組的遍歷,用下面介紹的Range類也能省不少代碼)
參考 http://en.cppreference.com/w/cpp/language/range-for 可知,
語句 for ( range_declaration : range_expression) loop_statement
與以下語句作用等價:
{ auto && __range = range_expression ; for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) { range_declaration = *__begin; loop_statement } }
對于可遍歷的類對象,__begin和__end分別由類的begin()和end()方法產(chǎn)生。且由于__range變量是右值引用,如果range_expression的結(jié)果是右值,其將會在循環(huán)結(jié)束后析構(gòu)。
--------------------------------------------------------------------------------
這樣,C++11終于支持了這種現(xiàn)代編程語言都支持的遍歷方式了。但是,無論是語法還是標(biāo)準(zhǔn)庫都不支持對具體數(shù)字的遍歷,比如python中的 for i in xrange(1,5)語句中,x將連續(xù)取[1,4]中的值。(Boost庫有irange類可以滿足這個需求,但是下面會討論下我的實現(xiàn))
最直接的方法,就是寫一個函數(shù),返回一個vector<int>對象,其元素為從begin到end的值。但這樣每次循環(huán)時都得構(gòu)造一個這樣的對象,略慢。
從標(biāo)準(zhǔn)來看,如果一個類要支持這樣遍歷,至少得有begin()和end()方法。在for循環(huán)的初始化部分,調(diào)用了這兩個方法之后,就沒這個類啥事了——都是迭代器的事。所以很自然,從迭代器上下手。這個迭代器必須支持三種操作:!=,前綴++,解引用
。有沒發(fā)現(xiàn),如果這個“迭代器”是個int數(shù)值的話,上面循環(huán)中的__begin!=__end;++__begin語句就是一個非常自然的實現(xiàn)。現(xiàn)在的目標(biāo)很簡單了:這個“迭代器”不遍歷容器中的每個元素,而就是一個簡單的int數(shù)值的封裝。對其解引用將返回這個數(shù)
,而比較和自加操作均對這個數(shù)進(jìn)行操作。
--------------------------------------------------------------------------------
有想法之后,實現(xiàn)起來就很容易了。首先定義一個仿迭代器 FakeIter ,其對一個數(shù)值進(jìn)行封裝,并重載必須的操作符。
class FakeIter { typedef long _VType; //數(shù)值的類型為long。當(dāng)然了,也可以寫個模板出來 public: explicit FakeIter(_VType val) :value_(val){} bool operator != (const FakeIter& other) const { return (this->GetValue()) != (other.GetValue()); } _VType operator* () const { return GetValue(); } const FakeIter& operator++ () { ++value_; return *this; } private: _VType GetValue() const { return value_; } _VType value_; };
至于“容器”類的實現(xiàn),就更簡單了:實現(xiàn)begin()和end()方法,并返回上面的FakeIter就好了。類中的方法加了一些cout語句,可以更清楚的了解循環(huán)執(zhí)行時具體方法的調(diào)用過程,實際用時可以刪掉。
class Range { typedef long _VType; //同樣,也可以弄個模板出來,但是就不方便用了 public: Range (_VType begin_v, _VType end_v) :begin_value_(begin_v), end_value_(end_v) { cout<<"Range::Range()"<<endl; } ~Range() { cout<<"Range::~Range()"<<endl; } FakeIter begin () const { cout<<"Range::begin()"<<endl; return FakeIter(begin_value_); } FakeIter end () const { cout<<"Range::end()"<<endl; return FakeIter(end_value_ ); } private: _VType begin_value_; _VType end_value_; };
好了,試試看這貨有沒用:
for (auto x: Range(1,5)) { std::cout<<x<<endl; } std::cout<<"Loop end"<<endl;
在vs2012及clang下輸出如下:
Range::Range() Range::begin() Range::end() 1 2 3 4 Range::~Range() Loop end
嗯,如果把那些影響視線的輸出語句的注釋掉的話貌似能用了。現(xiàn)在要遍歷一個new生成的數(shù)組的話,只需用這東西Range個下標(biāo),世界就清靜了。
但是,步長呢!好吧,貌似我暫時還沒這方面的需求。不過實現(xiàn)起來也很簡單:修改FakeIter類就可以了,可以增加一個表示步長的成員,然后再修改自加操作。更進(jìn)一步,也可以加一個生成器方法,就能變成一個更通用的生成器了。配合C++11 lambda操作符,用起來也挺方便。
以上就是小編為大家?guī)淼腃++11的for循環(huán),以及范圍Range類的簡單實現(xiàn)全部內(nèi)容了,希望大家多多支持腳本之家~
相關(guān)文章
C++默認(rèn)參數(shù)與函數(shù)重載及注意事項
這篇文章主要介紹了C++默認(rèn)參數(shù)與函數(shù)重載及注意事項包括語法與使用,通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值 ,需要的朋友可以參考下2020-03-03C++實現(xiàn)十六進(jìn)制字符串轉(zhuǎn)換成int整形值的示例
今天小編就為大家分享一篇關(guān)于C++實現(xiàn)十六進(jìn)制字符串轉(zhuǎn)換成int整形值的示例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12C語言 pthread_create() 函數(shù)講解
這篇文章主要介紹了C語言 pthread_create() 函數(shù)講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08