#include <iostream> #include <vector> int main(void) { std::vector<int> arr; // ... for(auto it = arr.begin(); it != arr.end(); ++it) { std::cout << *it << std::endl; } return 0; }上面借助前面介紹過的 C++ auto 關鍵字,省略了疊代器的宣告。
#include <algorithm> #include <iostream> #include <vector> void do_cout(int n) { std::cout << n << std::endl; } int main(void) { std::vector<int> arr; // ... std::for_each(arr.begin(), arr.end(), do_cout); return 0; }std::for_each 比起前面的 for 迴圈,最大的好處是不再需要關注疊代器(Iterator)的概念,只需要關心容器中的元素型別即可。
int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 }; foreach (int element in fibarray) { System.Console.WriteLine(element); }上面這段程式碼通過“foreach”關鍵字使用了基於範圍的 for 迴圈。可以看到,在這種 for 迴圈中,不再需要傳遞容器的兩端,迴圈會自動以容器為範圍展開,並且迴圈中也遮蔽掉了疊代器的遍歷細節,直接抽取出容器中的元素進行運算。
#include <iostream> #include <vector> int main(void) { std::vector<int> arr = { 1, 2, 3 }; // ... for(auto n : arr) //使用基於範圍的for迴圈 { std::cout << n << std::endl; } return 0; }在上面的基於範圍的 for 迴圈中,n 表示 arr 中的一個元素,auto 則是讓編譯器自動推匯出 n 的型別。在這裡,n 的型別將被自動推導為 vector 中的元素型別 int。
:
,之後直接寫上需要遍歷的表示式,for 迴圈將自動以表示式返回的容器為範圍進行疊代。
std::vector<int> arr;
for(int n : arr) ;
std::vector<int> arr;
for(char n : arr) ; // int會被隱式轉換為char
for(auto& n : arr) { std::cout << n++ << std::endl; }在完成上面的遍歷後,arr 中的每個元素都會被自加 1。
#include <iostream> #include <map> int main(void) { std::map<std::string, int> mm = { { "1", 1 }, { "2", 2 }, { "3", 3 } }; for(auto& val : mm) { std::cout << val.first << " -> " << val.second << std::endl; } return 0; }這裡需要注意兩點:
std::map<std::string, int> mm = { { "1", 1 }, { "2", 2 }, { "3", 3 } }; for(auto ite = mm.begin(); ite != mm.end(); ++ite) { std::cout << ite->first << " -> " << ite->second << std::endl; } for(auto& val : mm) // 使用基於範圍的for迴圈 { std::cout << val.first << " -> " << val.second << std::endl; }從這裡就可以很清晰地看出,在基於範圍的 for 迴圈中每次疊代時使用的型別和普通 for 迴圈有何不同。
#include <iostream> #include <set> int main(void) { std::set<int> ss = { 1, 2, 3 }; for(auto& val : ss) { // error: increment of read-only reference 'val' std::cout << val++ << std::endl; } return 0; }例子中使用 auto& 定義了 std::set<int> 中元素的參照,希望能夠在迴圈中對 set 的值進行修改,但 std::set 的內部元素是唯讀的——這是由 std::set 的特徵決定的,因此,for 迴圈中的 auto& 會被推導為 const int&。
#include <iostream> #include <vector> std::vector<int> arr = { 1, 2, 3, 4, 5 }; std::vector<int>& get_range(void) { std::cout << "get_range ->: " << std::endl; return arr; } int main(void) { for(auto val : get_range()) { std::cout << val << std::endl; } return 0; }輸出結果:
#include <iostream> #include <vector> int main(void) { std::vector<int>arr = { 1, 2, 3, 4, 5 }; for(auto val : arr) { std::cout << val << std::endl; arr.push_back(0); // 擴大容器 } return 0; }執行結果(32位元mingw4.8):
#include <iostream> #include <vector> int main(void) { std::vector<int> arr = { 1, 2, 3, 4, 5 }; auto && __range = (arr); for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin) { auto val = *__begin; std::cout << val << std::endl; arr.push_back(0); // 擴大容器 } return 0; }從這裡可以很清晰地看到,和我們平時寫的容器遍歷不同,基於範圍的 for 迴圈傾向於在迴圈開始之前確定好疊代的範圍,而不是在每次疊代之前都去呼叫一次 arr.end()。