**C++20 中的范围基 for 循环与 C++17 的区别**

在 C++11 之后,范围基 for 循环(Range‑Based for)已经成为遍历容器的首选方式。随着 C++20 的发布,这一语法又被进一步完善和扩展。本文将对 C++20 中范围基 for 循环的新特性进行梳理,并与 C++17 的实现做一一比较,帮助读者了解两者的异同以及在实际编码中的应用场景。


1. C++17 版本的基本语法回顾

for (auto&& element : container) {
    // 处理 element
}
  • auto&& 是一种通用引用,能兼容 lvalue 与 rvalue。
  • 编译器会在内部展开为以下逻辑(简化版):
auto && __range = container;
auto __begin = std::begin(__range);
auto __end   = std::end(__range);
for (; __begin != __end; ++__begin) {
    auto&& element = *__begin;
    // 处理 element
}
  • 适用范围:任何满足 begin() / end() 或者 cbegin() / cend() 的容器。

2. C++20 的新特性

2.1 范围运算符(ranges::for_each)的替代

C++20 引入了 `

` 库,提供了更加灵活的迭代器工具。虽然标准并没有直接改动范围基 for 的实现,但与之配合使用的工具使得循环更强大: “`cpp #include namespace r = std::ranges; for (auto&& e : r::view::filter(container, predicate)) { // 只遍历满足 predicate 的元素 } “` #### 2.2 `std::ranges::begin` / `std::ranges::end` 的统一 C++20 进一步统一了 `begin()` 和 `end()` 的调用方式,支持更广泛的类型(如 `std::initializer_list`、C 风格数组、甚至自定义类型)。使用 `std::ranges::begin` 能确保对所有支持的范围都能正确获取迭代器。 #### 2.3 结构化绑定与循环 C++17 已经支持结构化绑定,但在 C++20 中与范围基 for 的结合更为自然: “`cpp for (auto&& [key, value] : std::as_const(container)) { // key, value 分别是容器元素的成员 } “` 这在遍历 `std::map` 或自定义的键值对容器时非常方便。 #### 2.4 `ranges::for_each` 的直接使用 虽然不再是语法糖,但 `std::ranges::for_each` 提供了更直观的函数式风格: “`cpp std::ranges::for_each(container, [](auto&& e){ /* 处理 e */ }); “` 在并行化(`std::execution::par`)时也可以轻松切换: “`cpp std::ranges::for_each(std::execution::par, container, [](auto&& e){ /* … */ }); “` — ### 3. 两者在性能上的差异 – **迭代器获取**:C++20 通过 `std::ranges::begin` 可能会额外检查或调用自定义的 `begin()`,但在大多数实现中性能几乎相同。 – **结构化绑定**:C++20 在结构化绑定时对底层迭代器进行解构,编译器优化良好,不会产生明显额外开销。 – **并行执行**:C++17 的范围基 for 需要手动写并行逻辑;C++20 的 `std::ranges::for_each` 支持执行策略,能更轻松实现并行化。 — ### 4. 实际编码中的使用建议 | 场景 | 推荐写法 | 说明 | |——|———-|——| | 简单遍历容器 | `for (auto&& e : container)` | 传统且易读 | | 需要过滤元素 | `for (auto&& e : r::view::filter(container, pred))` | 通过视图实现懒惰过滤 | | 需要并行 | `std::ranges::for_each(std::execution::par, container, fn)` | 直接支持并行执行 | | 需要结构化绑定 | `for (auto&& [k, v] : container)` | 适用于键值对容器 | | 处理自定义范围 | `for (auto&& e : std::ranges::subrange(begin, end))` | 支持自定义迭代器范围 | — ### 5. 小结 – C++20 并没有彻底改写范围基 for 的内部实现,但与 ` ` 库的紧密结合,使得遍历更灵活、更强大。 – 通过 `std::ranges::begin` / `std::ranges::end`、视图(`view`)和执行策略,可以实现更高效、更易维护的代码。 – 对于大多数普通代码,C++17 的写法已经足够;当需要过滤、并行或结构化绑定时,C++20 的特性将大大提升表达能力。 希望本文能帮助你在日常 C++ 开发中,更好地运用范围基 for 循环与 C++20 的新特性。

发表评论