基于范围的for循环
C++98遍历方式
在C++98标准中,当我们遍历数组时,一般方法就是下标遍历和指针遍历。
int arr[] = { 1,2,3,5,6 }; // 下标遍历 for(size_t i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { std::cout << arr[i] << " "; } std::cout << std::endl; // 指针遍历 int* p = arr; for(p = arr; p < arr + sizeof(arr) / sizeof(arr[0]); ++p) { std::cout << *p << " "; } std::cout << std::endl;
当然还有一种遍历方式,需要包含<algorithm>
头文件的for_each
遍历。参数依次是:起始地址、结束地址、回调函数。地址是左闭右开区间[begin,end)
。
#include <iostream> #include <algorithm> void print(const int& elem) { std::cout << elem << " "; } // for_each遍历 std::for_each(arr, arr + sizeof(arr) / sizeof(arr[0]), print); std::cout << std::endl;
C++11 范围遍历
上述的几种遍历方式的共同点就是都需要写明循环的一个范围。对于我们需要完整的遍历一个有范围的集合/数组时,完全可以让编译器自动计算出范围。因此C++11引入了基于范围的for循环。
格式:for(迭代的变量:数组){}
现在我们使用范围遍历对数组进行遍历。
for(const int& e: arr) { std::cout << e << " "; } std::cout << std::endl;
然后我们可以在这里加入auto
自动类型(C++11),遍历将会更加简单。
for (const auto& elem : arr) { std::cout << elem << " "; } std::cout << std::endl;
但范围遍历不能适用于所有情况,范围遍历的条件就是循环迭代的范围必须是可确定的。例如string
、array
、vector
、list
、map
等都是可以正常使用的。而用户自定义写的类则需要自行提供自增运算符重载和赋值运算符重载。
int* ptr = arr; for(auto elem : ptr) { std::cout << elem << " "; } std::cout << std::endl;
遍历没有明确范围的数组,是不能使用范围遍历方法的。
在使用范围遍历的方式遍历stl的容器时,如果你使用auto声明迭代器的变量,那么推导出来的类型是迭代器解引用后的对象。
std::vector<int> vec{ 1,5,6,9,4 }; for (const auto iter = vec.begin(); iter != vec.end(); ++iter) { std::cout << *iter << " "; } std::cout << std::endl; for(const auto& elem : vec) { std::cout << elem << " "; } std::cout << std::endl;
这里就需要注意了前者iter
类型是迭代器对象,后者elem
是解引用后的对象。