Skip to content

Ch 10: 循环和迭代

  • 熟练使用传统 for 循环
  • 掌握 C++ 范围 for 循环
  • 理解 C++20 范围库视图
  • 学会选择合适的循环方式
# 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, 8
// 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 (初始化; 条件; 更新)
for (int i = 0; i < 5; ++i) {
// 初始化: int i = 0 - 只执行一次
// 条件: i < 5 - 每次迭代前检查
// 更新: ++i - 每次迭代后执行
}
#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;
}
# 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] # 过滤+转换
#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
}
#include <vector>
#include <ranges>
std::vector<int> nums = {1, 2, 3, 4, 5};
// iota - 类似 Python range
for (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)
#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; // 只是引用,不拷贝数据
# Python - enumerate
for i, item in enumerate(items):
print(f"{i}: {item}")
// C++23 有 std::views::enumerate
for (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 自己实现 enumerate
template<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]}; }
);
}
// C++ while
while (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;
}
// 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
while True:
process()
if not condition:
break
std::vector<int> nums = {1, 2, 3, 4, 5};
for (int n : nums) {
if (n == 3) break; // 遇到 3 停止
std::cout << n << " "; // 1 2
}
for (int n : nums) {
if (n % 2 == 0) continue; // 跳过偶数
std::cout << n << " "; // 1 3 5
}

带标签的 break(跳出多层循环)

Section titled “带标签的 break(跳出多层循环)”
// C++ 带标签的 break
outer:
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 或标志变量
# Python
for i in range(3):
for j in range(3):
if i == 1 and j == 1:
break
else:
continue
break
#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
}
#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;
}
#include <vector>
// 范围 for vs 传统 for
std::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) 类似 Python range()
  • while 循环条件在前,do-while 条件在后(至少执行一次)
  • break 跳出循环,continue 跳过本次迭代
  • 带标签的 break outer 可以跳出多层循环

下章预告:ch11 学习函数的声明、定义和参数传递。