Ranges庫的基本用法
什么是Ranges庫?
C++20引入的Ranges庫(<ranges>
)是一個強大的工具集,旨在簡化和增強對集合(如數組、向量等序列容器)的操作。它提供了一套用于操作序列的功能性接口,使得代碼更具可讀性和表達力。
Ranges庫的核心組件
- Views(視圖):可以看作是懶惰求值的序列操作,它們不改變底層容器,而是提供一種延遲計算的方式,直到實際需要結果時才執行計算。
- Actions(動作):類似于視圖,但它們是即時操作,會直接改變底層數據。
- Adaptors(適配器):用于將基本操作組合起來,生成復雜的操作序列。
- Range Factories(范圍工廠):用于生成新的范圍,例如
std::views::iota
可以生成一個從某個起點到終點的數值序列。
基本用法
1. 視圖(Views)
視圖是一種懶惰的、非變更性的操作,允許對序列進行篩選、轉換和組合。常見的視圖包括:
std::views::filter
:過濾視圖,根據給定的條件過濾序列中的元素。std::views::transform
:變換視圖,對序列中的每個元素應用一個變換函數。
示例:過濾和轉換
#include <iostream>
#include <vector>
#include <ranges>int main() {std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};// 使用filter視圖過濾出偶數auto even_numbers = numbers | std::views::filter([](int n) { return n % 2 == 0; });// 使用transform視圖將每個數平方auto squared_numbers = even_numbers | std::views::transform([](int n) { return n * n; });// 輸出結果for (int n : squared_numbers) {std::cout << n << " ";}return 0;
}
在這個示例中,even_numbers
視圖過濾出了偶數,squared_numbers
視圖將每個偶數平方。最終輸出結果是過濾和轉換后的序列。
2. 動作(Actions)
動作是即時執行的操作,會直接改變序列內容。在標準庫中,動作的支持較少,通常需要使用第三方庫(如Range-v3)才能看到完整的動作集合。
示例:排序和去重
#include <iostream>
#include <vector>
#include <ranges>
#include <algorithm>int main() {std::vector<int> numbers = {4, 2, 5, 1, 3, 2, 4, 5};// 使用std::ranges::sort進行排序std::ranges::sort(numbers);// 使用std::ranges::unique去重auto end_it = std::ranges::unique(numbers);numbers.erase(end_it.begin(), numbers.end());// 輸出結果for (int n : numbers) {std::cout << n << " ";}return 0;
}
在這個示例中,std::ranges::sort
對序列進行了排序,而std::ranges::unique
則移除了重復的元素。
3. 適配器(Adaptors)
適配器是組合多個操作的工具。例如,我們可以將過濾和轉換操作組合成一個適配器。
示例:組合過濾和轉換
#include <iostream>
#include <vector>
#include <ranges>int main() {std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};// 組合過濾和轉換操作auto even_squared = numbers | std::views::filter([](int n) { return n % 2 == 0; })| std::views::transform([](int n) { return n * n; });// 輸出結果for (int n : even_squared) {std::cout << n << " ";}return 0;
}
在這個示例中,我們將過濾和轉換操作組合成了一個視圖適配器,這使得代碼更簡潔。
4. 范圍工廠(Range Factories)
范圍工廠可以生成新的范圍。例如,std::views::iota
可以生成一個從起點到終點的數值序列。
示例:生成數值范圍
#include <iostream>
#include <ranges>int main() {// 使用std::views::iota生成一個從0到9的序列auto numbers = std::views::iota(0, 10);// 輸出結果for (int n : numbers) {std::cout << n << " ";}return 0;
}
這個示例中,std::views::iota
生成了一個從0到9的數值序列。
Ranges庫的優勢
- 代碼簡潔:通過使用視圖和適配器,代碼可以更簡潔地表達復雜的操作。
- 懶惰求值:視圖操作是惰性求值的,只有在實際需要結果時才會進行計算,這可以提高性能,尤其是在處理大型數據集時。
- 更高的表達力:Ranges庫的操作更具表達力,能更直觀地表達數據操作的意圖。
- 組合性:操作可以通過適配器進行組合,簡化了復雜的操作鏈。
通過C++20的Ranges庫,我們能夠更加優雅和高效地處理集合操作,使得代碼更加清晰、易讀和易于維護。