通八洲科技

C++20的范围(Ranges)库如何使用?(简化算法操作)

日期:2025-12-22 00:00 / 作者:穿越時空
c++kquote>C++20 ranges库通过views、actions和algorithms实现直观、安全、可组合的范围操作:views惰性适配、actions就地修改、algorithms单参数调用,支持管道链式表达与零开销组合。

C++20 的 ranges 库让算法操作更直观、更安全、更组合化——不用再传迭代器对,直接对容器或视图操作,链式调用清晰自然。

用 ranges 替代传统算法调用

传统写法需手动传递 begin()end(),容易出错且冗长:

// 传统方式:反转 vector 中满足条件的子序列(易错)
auto it1 = std::find_if(v.begin(), v.end(), pred);
auto it2 = std::find_if_not(it1, v.end(), pred);
std::reverse(it1, it2);

ranges 版本直接作用于范围,语义明确、无迭代器失效风险:

std::ranges::reverse(
std::ranges::subrange(
std::ranges::find_if(v, pred),
std::ranges::find_if_not(std::ranges::find_if(v, pred), pred)
)
);

更常用的是配合视图(views)链式表达:

auto result = v
| std::views::filter(pred)
| std::views::transform([](int x) { return x * 2; })
| std::views::take(5);

核心组件:views、actions、algorithms

views 是轻量、惰性求值的只读适配器,不拷贝数据,支持管道操作(|):

  • std::views::filter:筛选满足谓词的元素
  • std::views::transform:对每个元素做映射
  • std::views::take/drop:取前 N 个或跳过前 N 个
  • std::views::join:展平嵌套范围(如 vector>

actions 是就地修改原范围的操作(需左值),用法类似 views 但会改变数据:

  • std::ranges::sort(v) → 直接排序整个容器
  • v | std::views::filter(pred) | std::actions::sort → 先过滤再就地排序子序列(C++23 扩展,部分编译器已支持)

algorithms(如 std::ranges::findstd::ranges::count_if)接受单个范围参数,返回 iteratorbool 等,比传统算法更简洁安全。

常见实用技巧

  • 避免复制,优先用 views:视图不拥有数据,组合多个 view 几乎零开销
  • std::ranges::to() 提取结果auto evens = v | std::views::filter([](int x){return x%2==0;}) | std::ranges::to<:vector>();
  • 自定义 view 需继承 std::ranges::view_interface,并实现 begin()/end()
  • 注意 lifetime:视图引用原容器,确保原数据生命周期长于视图使用期

编译与兼容性提示

启用 C++20 并确认标准库支持(GCC 10.2+、Clang 13+、MSVC 19.30+):

g++ -std=c++20 -O2 your_file.cpp

头文件只需 (无需额外包含 ,但部分 view 可能需 等容器头)。

不复杂但容易忽略:ranges 是值语义 + 惰性计算的组合范式,习惯后代码更短、意图更清、错误更少。