Ch 10: 循环和迭代
- 熟练使用传统 for 循环
- 掌握 C++ 范围 for 循环
- 理解 C++20 范围库视图
- 学会选择合适的循环方式
10.1 Python for 循环
Section titled “10.1 Python for 循环”# Python - for 遍历任何可迭代对象for i in range(5): print(i) # 0, 1, 2, 3, 4
for item in items: print(item)
for i, item in enumerate(items): print(f"{i}: {item}")
for i in range(0, 10, 2): print(i) # 0, 2, 4, 6, 810.2 C++ 传统 for 循环
Section titled “10.2 C++ 传统 for 循环”// C++ - 类似 C/Java 的 for 循环for (int i = 0; i < 5; ++i) { std::cout << i << std::endl; // 0, 1, 2, 3, 4}
// 步进循环for (int i = 0; i < 10; i += 2) { std::cout << i << std::endl; // 0, 2, 4, 6, 8}
// 反向遍历for (int i = 4; i >= 0; --i) { std::cout << i << std::endl;}
// 遍历数组int arr[] = {1, 2, 3, 4, 5};for (int i = 0; i < 5; ++i) { std::cout << arr[i] << std::endl;}传统 for 的结构
Section titled “传统 for 的结构”// for (初始化; 条件; 更新)for (int i = 0; i < 5; ++i) { // 初始化: int i = 0 - 只执行一次 // 条件: i < 5 - 每次迭代前检查 // 更新: ++i - 每次迭代后执行}10.3 C++ 范围 for 循环
Section titled “10.3 C++ 范围 for 循环”#include <vector>
std::vector<int> nums = {1, 2, 3, 4, 5};
// 范围 for - 最接近 Python 的方式for (int n : nums) { std::cout << n << std::endl;}
// const 引用(避免拷贝)for (const auto& n : nums) { std::cout << n << std::endl;}
// 值拷贝for (auto n : nums) { // n 是拷贝}int arr[] = {1, 2, 3, 4, 5};for (int n : arr) { std::cout << n << std::endl;}
// 遍历字符串std::string s = "Hello";for (char c : s) { std::cout << c << std::endl;}10.4 C++20 std::views 范围
Section titled “10.4 C++20 std::views 范围”Python 风格的链式操作
Section titled “Python 风格的链式操作”# Python - 列表推导nums = list(range(1, 11))evens = [x for x in nums if x % 2 == 0] # 过滤squares = [x**2 for x in nums] # 转换combined = [x**2 for x in nums if x % 2 == 0] # 过滤+转换C++20 范围视图
Section titled “C++20 范围视图”#include <vector>#include <ranges>
std::vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 过滤偶数(C++20)auto evens = nums | std::views::filter([](int x) { return x % 2 == 0; });
// 转换(平方)auto squares = nums | std::views::transform([](int x) { return x * x; });
// 链式操作auto result = nums | std::views::filter([](int x) { return x % 2 == 0; }) | std::views::transform([](int x) { return x * x; });
// 惰性求值 - 不创建中间容器!for (int n : result) { std::cout << n << " "; // 4 16 36 64 100}常用视图操作
Section titled “常用视图操作”#include <vector>#include <ranges>
std::vector<int> nums = {1, 2, 3, 4, 5};
// iota - 类似 Python rangefor (int i : std::views::iota(0, 5)) { std::cout << i << " "; // 0 1 2 3 4}
// take - 取前 N 个for (int n : nums | std::views::take(3)) { std::cout << n << " "; // 1 2 3}
// drop - 跳过前 N 个for (int n : nums | std::views::drop(3)) { std::cout << n << " "; // 4 5}
// reverse - 反向for (int n : nums | std::views::reverse) { std::cout << n << " "; // 5 4 3 2 1}
// split / lazy_split(C++23)惰性求值原理
Section titled “惰性求值原理”#include <vector>#include <ranges>
std::vector<int> nums = {1, 2, 3, 4, 5};
// Python: [x**2 for x in nums if x % 2 == 0]// 这会立即创建新列表
// C++: 惰性求值auto result = nums | std::views::filter([](int x) { return x % 2 == 0; }) | std::views::transform([](int x) { return x * x; });
// 迭代时才计算for (int n : result) { // filter + transform 在这里执行 std::cout << n << std::endl;}
// 不迭代就不计算!auto r = result; // 只是引用,不拷贝数据C++23 std::views::enumerate
Section titled “C++23 std::views::enumerate”# Python - enumeratefor i, item in enumerate(items): print(f"{i}: {item}")// C++23 有 std::views::enumeratefor (auto [i, item] : items | std::views::enumerate) { std::cout << i << ": " << item << std::endl;}
// C++20 变通方案int i = 0;for (auto& item : items) { std::cout << i++ << ": " << item << std::endl;}
// C++20 自己实现 enumeratetemplate<std::ranges::input_range R>auto enumerate(R&& range) { return std::views::transform( std::views::iota(0UZ), [&, i = 0](auto) mutable { return std::pair{i++, range[i-1]}; } );}10.5 while 和 do-while
Section titled “10.5 while 和 do-while”while 循环
Section titled “while 循环”// C++ whilewhile (condition) { // 循环体}
// 遍历直到找到std::vector<int> nums = {3, 1, 4, 1, 5};int target = 4;std::size_t i = 0;while (i < nums.size() && nums[i] != target) { ++i;}if (i < nums.size()) { std::cout << "Found at index " << i << std::endl;}
// 无限循环while (true) { if (exit_condition) break;}do-while(至少执行一次)
Section titled “do-while(至少执行一次)”// C++ do-while - 循环体至少执行一次int choice;do { std::cout << "1. New game" << std::endl; std::cout << "2. Load game" << std::endl; std::cout << "3. Exit" << std::endl; std::cin >> choice;} while (choice < 1 || choice > 3);Python 没有 do-while
Section titled “Python 没有 do-while”# Python 需要模拟 do-whilewhile True: process() if not condition: break10.6 循环控制
Section titled “10.6 循环控制”break - 跳出循环
Section titled “break - 跳出循环”std::vector<int> nums = {1, 2, 3, 4, 5};
for (int n : nums) { if (n == 3) break; // 遇到 3 停止 std::cout << n << " "; // 1 2}continue - 跳过本次迭代
Section titled “continue - 跳过本次迭代”for (int n : nums) { if (n % 2 == 0) continue; // 跳过偶数 std::cout << n << " "; // 1 3 5}带标签的 break(跳出多层循环)
Section titled “带标签的 break(跳出多层循环)”// C++ 带标签的 breakouter:for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (i == 1 && j == 1) { break outer; // 直接跳出外层循环 } std::cout << "(" << i << "," << j << ") "; }}// 输出: (0,0) (0,1) (0,2) (1,0) (1,1) 这里停止
// Python 用 for-else 或标志变量# Pythonfor i in range(3): for j in range(3): if i == 1 and j == 1: break else: continue break10.7 范围 for 和容器
Section titled “10.7 范围 for 和容器”vector
Section titled “vector”#include <vector>
std::vector<int> v = {1, 2, 3};
for (int x : v) { /* ... */ }for (auto& x : v) { x *= 2; } // 修改for (const auto& x : v) { /* 只读 */ }#include <map>
std::map<std::string, int> ages = {{"Alice", 30}, {"Bob", 25}};
for (const auto& [name, age] : ages) { std::cout << name << ": " << age << std::endl;}#include <set>
std::set<int> s = {3, 1, 4, 1, 5, 9, 2, 6};
for (int x : s) { std::cout << x << " "; // 自动排序: 1 2 3 4 5 6 9}10.8 完整示例
Section titled “10.8 完整示例”#include <iostream>#include <vector>#include <ranges>#include <algorithm>
int main() { std::vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 传统 for 循环 std::cout << "Traditional: "; for (std::size_t i = 0; i < nums.size(); ++i) { std::cout << nums[i] << " "; } std::cout << std::endl;
// 范围 for std::cout << "Range-based: "; for (int n : nums) { std::cout << n << " "; } std::cout << std::endl;
// C++20 范围视图 - 过滤 + 转换 std::cout << "Evens squared: "; auto result = nums | std::views::filter([](int x) { return x % 2 == 0; }) | std::views::transform([](int x) { return x * x; });
for (int n : result) { std::cout << n << " "; // 4 16 36 64 100 } std::cout << std::endl;
// iota + take + filter std::cout << "iota(1, 11) filter odd: "; for (int i : std::views::iota(1, 11) | std::views::filter([](int x) { return x % 2 == 1; })) { std::cout << i << " "; // 1 3 5 7 9 } std::cout << std::endl;
// while 循环 std::cout << "While: "; std::size_t idx = 0; while (idx < nums.size()) { std::cout << nums[idx] << " "; ++idx; } std::cout << std::endl;
return 0;}10.9 性能考虑
Section titled “10.9 性能考虑”#include <vector>
// 范围 for vs 传统 forstd::vector<int> v(1000000);
// 范围 for(推荐)for (int x : v) { process(x);}
// 传统 for(用于需要索引时)for (std::size_t i = 0; i < v.size(); ++i) { process(v[i]);}
// 注意:end() 调用优化// 好的编译器会缓存 v.end()// 但某些情况下手动缓存可能有帮助for (auto it = v.begin(), end = v.end(); it != end; ++it) { // ...}- 传统
for (init; cond; incr)循环 - 范围
for (auto x : container)最接近 Python - C++20
std::views::filter/transform惰性求值 std::views::iota(begin, end)类似 Pythonrange()while循环条件在前,do-while条件在后(至少执行一次)break跳出循环,continue跳过本次迭代- 带标签的
break outer可以跳出多层循环
下章预告:ch11 学习函数的声明、定义和参数传递。