C++20特性:ranges & views

ranges 和 views 简介

ranges

    std::ranges 是 C++20 引入的一个新库,它将“范围(range)”作为一等公民。一个 range 是任何可以迭代的对象,比如数组、容器、生成器等。

    它提供了类型安全、更简洁的算法接口,例如:

// C++98 风格
sort(vec.begin(), vec.end());

// C++20 风格
ranges::sort(vec);

    无需再写 .begin().end(),更安全、更直观。


views

    std::views 是 Ranges 库中的核心组件。View 是一个不拥有数据的轻量级范围,它只是对原始数据提供一种“视图”或“投影”。

关键特性:

  • 零拷贝:不复制原始数据。
  • 延迟计算(Lazy Evaluation):只有在迭代时才真正执行操作。
  • 可组合:多个视图可通过 | 链式组合。

管道运算符 |

    C++20 重载了 | 运算符,用于将一个范围“传递”给一个视图适配器,形成链式调用。

auto result = data
    | views::filter(pred)
    | views::transform(f)
    | views::take(5);

常用 Views 操作详解

1. filter

    按条件筛选元素。

基本语法:

auto filtered = range | views::filter(predicate);
  • filtered 为一个名为 filtered 的视图对象。    
  • predicate 是一个一元谓词函数(返回 bool),用于判断每个元素是否保留。

应用:

vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};

auto filtered = vec | views::filter([](int x){ return x % 2 == 0; });

for (auto x : filtered)
    cout << x << ' ';

    作用:从一个容器中筛选出所有的偶数,并打印出来。

    如果单纯只输出,以上代码可写为:

vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};

for (auto x : vec | views::filter([](int x){ return x % 2 == 0; }))
    cout << x << ' ';

    结果:2 4 6 8


2. transform

    映射/转换每个元素。

基本语法:

auto transformed = range | views::transform(func);
  • transformed 为一个名为 transformed 的视图对象。    
  • func 接收一个元素,返回转换后的值(类型可以不同)。

应用:

vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};

auto transformed = vec | views::transform([](int x){ return to_string(x); });
    
for (auto x : transformed)
    cout << x << ' ';

    作用:将容器中的所有元素转换成字符串,并打印出来。

    如果单纯只输出,以上代码可写为:

vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};

for (auto x : vec | views::transform([](int x){ return to_string(x); }))
    cout << x << ' ';

    结果:1 2 3 4 5 6 7 8 9


3.reverse

    反转遍历顺序。

基本语法:

auto reversed = range | views::reverse;
  • reversed 为一个名为 reversed 的视图对象。    

应用:

vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};

for (auto x : vec | views::reverse)
    cout << x << ' ';

    结果:9 8 7 6 5 4 3 2 1

    作用:将容器逆序输出。


4. take / drop

    截取或跳过元素。

基本语法:

auto first_n  = range | views::take(n);   // 前 n 个
auto skip_n   = range | views::drop(n);   // 跳过前 n 个

详细说明:   

操作行为
take(n)最多取 n 个元素。如果不足 n 个,就取完为止。
drop(n)跳过前 n 个元素,返回剩余部分。若总数 ≤ n,则为空。

    优点:不会越界,行为定义良好。

应用:

vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};

for (auto x : vec | views::take(5) | views::drop(2))
    cout << x << ' ';

    结果:3 4 5

    作用:输出容器前五个元素并跳过前两个元素。

    注意:views 的顺序不一样结果也不一样

vector<int> vec{1, 2, 3, 4, 5, 6, 7, 8, 9};

for (auto x : vec | views::drop(2) | views::take(5))
    cout << x << ' ';

    结果:3 4 5 6 7


5. join

    扁平化嵌套结构。

基本语法:

auto flat = nested_range | std::views::join;
  • flat 为一个名为 flat 的视图对象。    
  • 要求内层也是一个 range,即“范围的范围”(range<range<T>>)。
  • 可以将容器降低一个维度。

应用:

vector<vector<int>> vec{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

for (auto x : vec | views::join)
    cout << x << ' ';

    结果:1 2 3 4 5 6 7 8 9

    作用:将二维 vector 输出成一维 vector


综合示例

vector<vector<int>> vec = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}};

auto ans = vec | views::join // 扁平化为一维: 1 2 3 4 5 6 7 8 9 10 11 12
           | views::drop(1)  // 跳过第一个元素: 2 3 4 5 6 7 8 9 10 11 12
           | views::take(5)  // 取前5个: 2 3 4 5 6
           | views::transform([](int n){ return n * n; }) // 转换为平方: 4 9 16 25 36
           | views::filter([](int n){ return n % 2 == 0; }) // 只取偶数: 4 16 36
           | views::reverse; // 反转: 36 16 4

for (int x : ans)
    cout << x << ' ';

    结果:36 16 4

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇