范圍for循環:
1.基於范圍的for循環
for(元素類型 元素對象:容器對象)
{
循環體
}
(1.1)如果循環體由單條語句或者單個結構塊組成,可以省略花括號
(1.2)用元素對象依次結合容器對象中的每一個元素,每結合一個元素,執行依次循環體,直至容器內的所有元素都被結合完為止.
(1.3)不依賴於下標元素,通用
(1.4)不需要訪問迭代器,透明
(1.5)不需要定義處理函數,簡潔
#include "stdafx.h" #include <iostream> #include <vector> #include <algorithm> using namespace std; void print(int i) { cout << i << " "; } int main() { int ai[]{ 65, 66, 67, 68, 69 }; //計算數組元素個數 size_t size = sizeof(ai) / sizeof(ai[0]); vector<int> vi(ai, ai + size); //基於下標運算的for循環,不是所有的容器都支持下標運算,不通用 for (size_t i = 0; i < size; ++i) cout << ai[i] << " "; cout << endl; for (size_t i = 0; i < vi.size(); ++i) cout << vi[i] << " "; cout << endl; //基於迭代器的for循環,需要指明容器兩端,且對迭代器做自增,必須了解迭代器的運算規則,不夠透明 for (int *it = ai; it != ai + size; ++it) cout << *it << " "; cout << endl; for (auto it = vi.begin(); it != vi.end(); ++it) cout << *it << " "; cout << endl; //基於泛型函數的for循環,需要提供針對元素的處理函數,對於一般性遍歷而言比較繁瑣 for_each(ai, ai + size, print); cout << endl; for_each(vi.begin(), vi.end(), print); cout << endl; for (auto a : ai) cout << a << " "; cout << endl; for (auto a : vi) cout << a << " "; cout << endl; for (auto &a : ai) ++a; for (auto &a : vi) --a; for (auto const &a : ai) cout << a << " "; cout << endl; for (auto const &a : vi) cout << a << " "; cout << endl; for (char a : ai) cout << a << " "; cout << endl; for (char a : vi) cout << a << " "; cout << endl; return 0; }
2.范圍循環的注意事項
(2.1)對map和multimap容器使用范圍循環,每次拿到的元素既不是鍵也不是值,而是由鍵和值組成的pair
(2.2)在使用基於范圍的for循環時,不能違背容器本身的約束
(2.3)基於范圍的for循環,無論循環體執行多少次,冒號后面的表達式永遠只執行一次
(2.4)基於范圍的for循環,其底層實現依然要借助於容器的迭代器,
因此任何可能導致迭代器失效的結構性改變,都可能引發未定義的后果
#include <iostream> #include <string> #include <map> #include <list> using namespace std; list<int> getScores(void) { cout << __FUNCTION__ << endl; return{ 70, 75, 80, 85, 90, 95 }; } int main() { //對map和multimap容器使用范圍循環,每次拿到的元素既不是鍵也不是值,而是由鍵和值組成的pair multimap<string, int> msi; msi.insert(make_pair("張飛", 100)); msi.insert(make_pair("趙雲", 90)); msi.insert(make_pair("關羽", 80)); for (auto c : msi) cout << c.first << ":" << c.second << endl; cout << endl; for (auto it = msi.begin(); it != msi.end(); ++it) cout << it->first << ":" << it->second << endl; cout << endl; //在使用基於范圍的for循環時,不能違背容器本身的約束 /*for (pair<string,int> &c:msi) if (c.first == "張飛") c.first = "張菲菲";*/ for (auto c : msi) cout << c.first << ":" << c.second << endl; cout << endl; //基於范圍的for循環,無論循環體執行多少次,冒號后面的表達式永遠只執行一次 for (auto score : getScores()) cout << score << " "; cout << endl; auto scores = getScores(); for (auto score : scores) { cout << score << " "; //基於范圍的for循環,其底層實現依然要借助於容器的迭代器, //因此任何可能導致迭代器失效的結構性改變,都可能引發未定義的后果 //scores.pop_front(); } cout << endl; return 0; }
3.使自己定義的容器類型支持范圍循環
一個類只要提供了分別獲取起始和終止迭代器的begin和end函數,就可以支持基於范圍的for循環
#include "stdafx.h" #include <iostream> using namespace std; template <typename T, size_t S> class Array { public: T &operator[](size_t i) { return m_array[i]; } T const &operator[](size_t i)const { return const_cast<Array&>(*this)[i]; } //獲取起始迭代器 T *begin() { return m_array; } T const *begin()const { return const_cast<Array *>(this)->begin(); } //獲取終止迭代器 T *end() { return m_array + S; } T const *end()const { return const_cast<Array *>(this)->end(); } private: T m_array[S]; }; int main() { int i = 0; Array<int, 5> ai; for (auto &a : ai) a = ++i * 10; auto const &cai = ai; for (auto &a : cai) cout << /*++*/a << " "; cout << endl; return 0; }