国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++11的for循環,以及范圍Range類的簡單實現

2020-05-23 14:02:35
字體:
來源:轉載
供稿:網友

C++11支持range-based for循環。這是一個很方便的特性,能省挺多代碼。以下代碼就能很方便的遍歷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;}

可以遍歷的對象包括:

•數組。(不包括指針)
•定義了begin()和end()方法,且返回該方法返回迭代器的類對象。(STL 中所有容器都可以)

(對于動態生成的數組的遍歷,用下面介紹的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()方法產生。且由于__range變量是右值引用,如果range_expression的結果是右值,其將會在循環結束后析構。

--------------------------------------------------------------------------------

這樣,C++11終于支持了這種現代編程語言都支持的遍歷方式了。但是,無論是語法還是標準庫都不支持對具體數字的遍歷,比如python中的 for i in xrange(1,5)語句中,x將連續取[1,4]中的值。(Boost庫有irange類可以滿足這個需求,但是下面會討論下我的實現)

最直接的方法,就是寫一個函數,返回一個vector<int>對象,其元素為從begin到end的值。但這樣每次循環時都得構造一個這樣的對象,略慢。

從標準來看,如果一個類要支持這樣遍歷,至少得有begin()和end()方法。在for循環的初始化部分,調用了這兩個方法之后,就沒這個類啥事了——都是迭代器的事。所以很自然,從迭代器上下手。這個迭代器必須支持三種操作:!=,前綴++,解引用
。有沒發現,如果這個“迭代器”是個int數值的話,上面循環中的__begin!=__end;++__begin語句就是一個非常自然的實現。現在的目標很簡單了:這個“迭代器”不遍歷容器中的每個元素,而就是一個簡單的int數值的封裝。對其解引用將返回這個數

,而比較和自加操作均對這個數進行操作。

--------------------------------------------------------------------------------

有想法之后,實現起來就很容易了。首先定義一個仿迭代器 FakeIter ,其對一個數值進行封裝,并重載必須的操作符。

class FakeIter{ typedef long _VType; //數值的類型為long。當然了,也可以寫個模板出來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_;};

至于“容器”類的實現,就更簡單了:實現begin()和end()方法,并返回上面的FakeIter就好了。類中的方法加了一些cout語句,可以更清楚的了解循環執行時具體方法的調用過程,實際用時可以刪掉。

 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

嗯,如果把那些影響視線的輸出語句的注釋掉的話貌似能用了?,F在要遍歷一個new生成的數組的話,只需用這東西Range個下標,世界就清靜了。

但是,步長呢!好吧,貌似我暫時還沒這方面的需求。不過實現起來也很簡單:修改FakeIter類就可以了,可以增加一個表示步長的成員,然后再修改自加操作。更進一步,也可以加一個生成器方法,就能變成一個更通用的生成器了。配合C++11 lambda操作符,用起來也挺方便。

以上就是小編為大家帶來的C++11的for循環,以及范圍Range類的簡單實現全部內容了,希望大家多多支持VEVB武林網~

 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 大同市| 龙陵县| 鹤山市| 泾源县| 嘉善县| 孟州市| 红原县| 贡山| 喜德县| 怀远县| 巩义市| 阜城县| 巴彦淖尔市| 南京市| 临夏市| 辉南县| 永定县| 怀安县| 温泉县| 四子王旗| 开封市| 汉沽区| 萨嘎县| 乐亭县| 南靖县| 东港市| 衡南县| 额敏县| 长治县| 靖江市| 内江市| 岳池县| 车险| 南投县| 林芝县| 绥滨县| 阿克陶县| 筠连县| 闸北区| 连州市| 斗六市|