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 进行了以下优化:
-
const与auto的更好推断
当容器元素为const时,循环变量默认也为const,避免不小心修改。 -
支持
std::initializer_list的for语法for (int x : {1,2,3}) { … } -
可在循环内部使用
auto&与auto&&的更细粒度控制
让我们可以在需要修改元素时使用引用,在只读时使用值。 -
与
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 带来的便捷与强大!