关于C++20中的新特性 ranges和views的学习

ranges

views

std::views::transform

特点

  • 惰性求值:转换操作不会立即执行,只有在你迭代这个视图时,lambda 函数才会应用到每个元素。
  • 不修改原容器,仅生成一个转换后的视图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <ranges>

int main() {
std::vector<int> v = {1, 2, 3, 4, 5};

// 构造一个视图,每个元素乘以 2
auto transformed_view = v | std::views::transform([](int n) { return n * 2; });

for (int n : transformed_view) {
std::cout << n << " "; // 输出: 2 4 6 8 10
}
return 0;
}

std::views::filter

创建一个视图,该视图仅包含满足给定谓词条件的元素,同样是惰性计算的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <ranges>

int main() {
std::vector<int> v = {1, 2, 3, 4, 5, 6};

// 构造一个视图,只保留偶数元素
auto filtered_view = v | std::views::filter([](int n) { return n % 2 == 0; });

for (int n : filtered_view) {
std::cout << n << " "; // 输出: 2 4 6
}
return 0;
}

std::views::take

用于构造一个视图,该视图只“取”原始范围的前 n 个元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <ranges>

int main() {
std::vector<int> v = {10, 20, 30, 40, 50};

// 构造一个视图,只取前 3 个元素
auto take_view = v | std::views::take(3);

for (int n : take_view) {
std::cout << n << " "; // 输出: 10 20 30
}
return 0;
}

std::views::drop

创建一个视图,跳过原始范围的前 n 个元素,只返回剩余部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <ranges>

int main() {
std::vector<int> v = {10, 20, 30, 40, 50};

// 构造一个视图,跳过前 2 个元素
auto drop_view = v | std::views::drop(2);

for (int n : drop_view) {
std::cout << n << " "; // 输出: 30 40 50
}
return 0;
}

std::views::reverse

用于构造一个反向视图,不会修改原容器,只是在遍历时以相反顺序访问元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <ranges>

int main() {
std::vector<int> v = {1, 2, 3, 4, 5};

// 构造一个反向视图
auto rev_view = v | std::views::reverse;

for (int n : rev_view) {
std::cout << n << " "; // 输出: 5 4 3 2 1
}
return 0;
}

或者说

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <vector>
#include <ranges>

int main() {
std::vector<int> v = {1, 2, 3, 4, 5};

// 通过 std::views::reverse 创建一个反向视图
for (int n : v | std::views::reverse) {
std::cout << n << " "; // 输出: 5 4 3 2 1
}

return 0;
}

std::views::drop_last

它用于生成一个新的视图,去掉原始范围的最后 n 个元素。与 std::views::drop 类似,std::views::drop_last 也是一个惰性求值的操作符,它不会修改原容器,而是按需返回一个新的视图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <vector>
#include <ranges>

int main() {
std::vector<int> v = {1, 2, 3, 4, 5};

// 使用 drop_last 去掉最后两个元素
auto view = v | std::views::drop_last(2);

for (int n : view) {
std::cout << n << " "; // 输出: 1 2 3
}

return 0;
}

边界条件

  • 如果你指定的n大于等于容器的元素个数,结果将是一个空视图。例如:

    1
    auto empty_view = v | std::views::drop_last(10);

    这样就会得到一个空视图,因为容器中没有足够的元素可以去除。

这些函数可以通过管道运算符叠加使用(链式操作)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <vector>
#include <ranges>

int main() {
std::vector<int> v = {1, 2, 3, 4, 5, 6};

// 使用 std::views::reverse 和 std::views::filter 链接,逆序并筛选掉奇数元素
for (int n : v | std::views::reverse | std::views::filter([](int n) { return n % 2 == 0; })) {
std::cout << n << " "; // 输出: 6 4 2
}

return 0;
}

关于C++20中的新特性 ranges和views的学习
http://example.com/2025/02/13/2025-02-13-关于C++20中的新特性-ranges和views的学习/
作者
Kiriao
发布于
2025年2月13日
许可协议