C++20 中的范围 for 循环与折叠表达式

C++20 为语言带来了许多强大的特性,其中两大亮点是改进后的范围 for 循环和折叠表达式(fold expressions)。这两者在编写简洁、安全、性能更佳的代码时发挥着重要作用。下面我们分别详细解读它们,并给出实用的使用案例。

1. 范围 for 循环的改进

1.1 传统写法的局限

std::vector <int> v{1,2,3,4,5};
for (auto it = v.begin(); it != v.end(); ++it) {
    std::cout << *it << ' ';
}
  • 手动使用迭代器容易出现越界或忘记 ++it 的错误。
  • 对容器的内部实现细节过度暴露,导致代码耦合度提高。

1.2 C++11 的范围 for

for (auto&& val : v) {
    std::cout << val << ' ';
}
  • 更直观、简洁,隐式获取 begin()end()
  • 支持 auto&& 来避免不必要的复制。

1.3 C++20 的进一步改进

C++20 对范围 for 进行了以下优化:

  1. constauto 的更好推断
    当容器元素为 const 时,循环变量默认也为 const,避免不小心修改。

  2. 支持 std::initializer_listfor 语法

    for (int x : {1,2,3}) { … }
  3. 可在循环内部使用 auto&auto&& 的更细粒度控制
    让我们可以在需要修改元素时使用引用,在只读时使用值。

  4. std::ranges 结合使用时更加流畅

    std::ranges::sort(v);
    for (auto&& val : v | std::views::filter([](int n){ return n%2==0; })) {
        std::cout << val << ' ';
    }

1.4 实际案例:筛选并修改

std::vector <int> nums{1,2,3,4,5,6};

for (auto& n : nums) {            // 引用可修改
    if (n % 2 == 0) n *= 10;      // 双倍偶数
}

for (auto&& n : nums) {            // 只读,使用 const
    std::cout << n << ' ';        // 结果:1 20 3 40 5 60
}

2. 折叠表达式(Fold Expressions)

折叠表达式是模板元编程中对可变参数包进行聚合操作的强大工具。它允许我们一次性完成 +, *, &&, ||, , 等运算的折叠。

2.1 基础语法

template<typename... Args>
auto sum(Args... args) {
    return (... + args);   // 左折叠
}
  • (... + args) 等价于 (((args1 + args2) + args3) + ...)

2.2 右折叠与二元折叠

(... + args)   // 左折叠
(args + ...)   // 右折叠
((... + args) + initial)  // 二元折叠

2.3 与 std::initializer_list 结合

template<typename... Args>
auto product(Args... args) {
    return (... * args);  // 折叠乘积
}

2.4 高级案例:运行时参数检查

template<typename T, typename... Args>
bool all_positive(const T& first, const Args&... rest) {
    return (first > 0) && (... && (rest > 0));
}

使用:

if (all_positive(3, 4, 5, 6)) {
    std::cout << "All positive!\n";
}

2.5 结合 constexpr 的编译期计算

constexpr int factorial(int n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

constexpr int result = factorial(5);  // 编译期求值

虽然不是折叠表达式,但结合 constexpr 能够在编译期完成递归计算。

3. 小结

  • 范围 for 的改进让代码更简洁、安全,并能与 std::ranges 无缝配合。
  • 折叠表达式 提升了可变参数模板的表达力,能一次性完成复杂聚合操作,避免手写循环。
  • 这两项特性在现代 C++ 开发中尤为重要,熟练掌握可以显著提高代码质量与开发效率。

尝试将上述技巧应用到你的项目中,体会 C++20 带来的便捷与强大!

发表评论