C++20引入了范围库(Ranges library),它是标准模板库(STL)的一个扩展,提供了一种新的方式来处理序列和范围。这个库允许开发者以更声明式的方式编写代码,使得操作序列变得更简洁、更易读。以下是C++范围库的关键特性和使用示例:
1. ranges::view
- 视图
视图是对数据范围的引用,而不会创建数据的副本。它们是延迟求值的,仅在需要时才计算元素。
#include <ranges>
#include <iostream>
#include <vector>
void viewExample() {
std::vector<int> nums = {0, 1, 2, 3, 4, 5};
auto evenNums = nums | std::views::filter([](int n) { return n % 2 == 0; });
for (int n : evenNums) {
std::cout << n << ' '; // 输出:0 2 4
}
}
2. ranges::actions
- 动作
动作类似于算法,但它们可以直接修改容器。
#include <ranges>
#include <vector>
#include <iostream>
void actionExample() {
std::vector<int> nums = {0, 1, 2, 3, 4, 5};
nums |= std::ranges::actions::remove_if([](int n) { return n % 2 == 0; });
for (int n : nums) {
std::cout << n << ' '; // 输出:1 3 5
}
}
3. 管道操作
C++20范围库允许你以管道的方式链式调用算法,使得代码更加直观。
#include <ranges>
#include <iostream>
#include <vector>
void pipelineExample() {
std::vector<int> nums = {1, 2, 3, 4, 5, 6};
auto result = nums
| std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n * n; });
for (int n : result) {
std::cout << n << ' '; // 输出:4 16 36
}
}
4. 惰性求值
范围操作通常是惰性求值的,这意味着计算会延迟进行,直到真正需要元素的值时才会执行。
#include <ranges>
#include <vector>
#include <iostream>
void lazyEvaluationExample() {
std::vector<int> nums = {1, 2, 3, 4, 5, 6};
auto squares = nums | std::views::transform([](int n) { return n * n; });
std::cout << *squares.begin() << std::endl; // 输出:1 (只计算了第一个元素的平方)
}
5. 与现有STL算法的兼容性
C++20范围库设计时考虑了与现有STL算法的兼容性,让你可以无缝地在旧代码中应用新的范围功能。
#include <ranges>
#include <algorithm>
#include <vector>
#include <iostream>
void compatibilityExample() {
std::vector<int> nums = {1, 2, 3, 4, 5, 6};
auto evenNums = nums | std::views::filter([](int n) { return n % 2 == 0; });
std::cout << std::ranges::count(evenNums, 4) << std::endl; // 输出:1
}
通过这些示例,你可以看到C++范围库如何提供一种更现代、更声明式的方式来处理序列和范围,它使得代码更加简洁且易于理解。