Loading... `range-based for loop`是`c++11`中引入的新的语法,例如: ```cpp // c++11 std::vector<int> arr {1, 2, 3, 4}; for (const auto &each : arr) { std::cout << each << " "; } std::cout << std::endl; // 输出 // 1 2 3 4 ``` ## 语法解释 ```cpp for (range_declaration : range_expression) { loop_statement } ``` 这个是`range-based for loop`的语法,这个语法在`c++11`、`c++14`标准等同于 ```cpp { auto && __range = range_expression; for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++_begin) { range_declaration = *__begin; loop_statement } } ``` 在`c++17`标准中等同于 ```cpp { auto && __range = range_expression; auto __begin = begin_expr; auto __end = end_expr; for ( ; __begin != __end; ++__begin) { range_declaration = *__begin; loop_statement } } ``` ## range-based for loop解析的三个原则 1. 如果`range_expression`为数组 ```cpp begin_expr = __range; end_expr = (__range + __bound) ``` 其中,`__bound`是固定大小数组的长度(如果长度未知,则程序是有问题的,一般情况编译器会报错) 2. 如果`range_expression`是一个类,且这个类有名为`begin`和`end`的成员函数 ```cpp begin_expr = __range.begin(); end_expr = __range.end(); ``` 3. 如果不满足上述要求,那么编译器会使用`ADL`查找符合条件的函数,如下所示 ```cpp begin_expr = begin(__range); end_expr = end(__range); ``` > 这里的begin函数和end函数可以在命名空间中,`ADL`都会找到匹配的函数 ## 自定义类的range-based for loop 根据上面三个原则中的后两个,以及“语法解释”中C++扩展的代码可知,我们的自定义类`Foo`需要实现 1. `begin`和`end`方法,这两个方法要么是`Foo`的成员函数,要么这两个方法接受`Foo`作为其参数 > 根据“range-based for loop解析的三个原则”中的第二第三点 2. `begin`和`end`方法需要返回某各类,我们这里命名为`FooInterator`,这个类需要实现`!=`和`++`的重载 > 根据“语法解析”中,`__begin != __end`和`++__begin`这两部分代码 > `FooIterator`也可以是指针,指针原生支持`!=`和`++`运算符 ## 例子 ### 例子1 ```cpp #include <iostream> class IntArray3 { public: IntArray3() : arr_{1, 2, 3} {} int* begin() { return arr_; } int* end() { return arr_ + 3; } private: int arr_[3]; }; int main(int argc, char** argv) { IntArray3 arr; for (const auto &each : arr) { std::cout << each << " "; } std::cout << std::endl; return -1; } ``` ### 例子2 ```cpp #include <iostream> class IntArray3 { public: IntArray3() : arr_{1, 2, 3} {} private: int arr_[3]; friend int* begin(IntArray3 &arr); friend int* end(IntArray3 &arr); }; int* begin(IntArray3 &arr) { return arr.arr_; } int* end(IntArray3 &arr) { return arr.arr_ + 3; } int main(int argc, char** argv) { IntArray3 arr; for (const auto &each : arr) { std::cout << each << " "; } std::cout << std::endl; return -1; } ``` ## Ref 1. https://en.cppreference.com/w/cpp/language/range-for Last modification:June 10, 2021 © Allow specification reprint Like If you think my article is useful to you, please feel free to appreciate