目錄前言介紹舉例: 前言 不錯麼 內容參考 https://zh.cppreference.com/w/cpp/ranges Chatjpt 總結註意點: 確保你的C++編譯器支持C++20標準 包含 ranges 頭文件 views的操作是惰性的,它們不會立即執行,而是在需要時計算。這意味著你可以 ...
目錄
前言
不錯麼
內容參考
總結註意點:
- 確保你的C++編譯器支持C++20標準
- 包含 ranges 頭文件
- views的操作是惰性的,它們不會立即執行,而是在需要時計算。這意味著你可以構建複雜的管道,而不必擔心性能問題。提供性能優勢,因為它們避免了不必要的數據拷貝和臨時存儲。在處理大型數據集時,這種優化尤為重要。
- 使用views不會修改原始數據,它們只是提供了對數據的查看和操作方式。因此,原始數據保持不變,不會被修改。
- 要小心處理可能的異常情況,例如範圍越界或無效的操作。可以使用try-catch塊來處理異常。
- 管道操作符 |(豎線符號)=>數據處理操作可以從左到右依次執行,
介紹
C++20引入了Ranges庫,其中的views
是該庫的一個關鍵組成部分。views
提供了一種現代化的、功能強大的方法來處理數據序列,它基於"range-based"編程範式,允許你以聲明性的方式對數據序列進行操作,而無需手動編寫迴圈。以下是關於views
的詳細介紹:
-
什麼是
views
?views
是C++20中Ranges庫的一部分,它代表了一個數據序列的虛擬視圖。這個視圖允許你以一種便捷和現代的方式訪問和操作數據,同時不需要實際地拷貝或修改原始數據。views
的操作是惰性的,只有在需要的時候才會執行。 -
視圖的創建:
你可以通過調用標準容器的
views
成員函數或使用適配器來創建視圖。例如,可以使用std::vector
創建一個視圖:std::vector<int> numbers = {1, 2, 3, 4, 5}; auto view = numbers | std::views::transform([](int x) { return x * 2; });
在這裡,
std::views::transform
是一個視圖適配器,它將一個函數應用於容器中的每個元素,創建一個新的視圖。 -
視圖的操作:
一旦創建了視圖,你可以對其執行各種操作,這些操作包括但不限於:
-
篩選(filtering):篩選出滿足特定條件的元素。
-
映射(mapping):將函數應用於序列中的每個元素。
-
切片(slicing):選擇範圍內的元素。
-
排序(sorting):對元素進行排序。
你可以將多個操作組合在一起來創建複雜的數據處理管道,而這些操作都是惰性執行的。
-
-
遍歷視圖:
一旦創建了視圖,你可以使用
for
迴圈或範圍for
迴圈來遍歷它。視圖會在遍歷時動態計算元素,而不會一次性生成所有元素。for (int num : view) { std::cout << num << " "; }
-
性能優勢:
views
具有優化的性能。它們避免了不必要的數據拷貝和臨時存儲,使得在處理大型數據集時非常高效。 -
自定義視圖:
你還可以創建自定義的視圖,通過實現必要的迭代器和操作符來定義你自己的數據序列操作。
-
views
的應用場景:views
適用於各種應用場景,包括數據轉換、篩選、數據流處理、映射、集合操作等。它們可以使你的代碼更加清晰、可讀和高效。
總之,views
是C++20引入的一個重要特性,它使得序列處理變得更加簡單和現代化。它們提供了一種優雅的方式來處理數據序列,避免了繁瑣的手動迭代和數據操作。在使用時,請確保你的編譯器支持C++20標準並瞭解如何正確使用Ranges庫以發揮其強大的功能。
舉例:
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用views::transform將每個元素翻倍=>2 4 6 8 10
auto doubled = numbers | std::views::transform([](int x) { return x * 2; });
// 使用views::filter篩選偶數 =>2 4
auto evenNumbers = numbers | std::views::filter([](int x) { return x % 2 == 0; });
// 使用views::slice選擇範圍[1, 3)=> 2 3 4
auto slicedRange = numbers | std::views::slice(1, 4);
// 鏈式操作:篩選偶數,然後翻倍=>4 8
auto result = numbers | std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * 2; });
// 使用views::iota生成範圍[1, 10)=>1~9
auto sequence = std::views::iota(1, 10);
// 生成無限遞增序列~~~
auto infiniteSequence = std::views::iota(1);
// 使用views::reverse反向迭代容器=>5 4 3 2 1
auto reversed = numbers | std::views::reverse;
// 使用views::concat合併兩個容器
std::vector<int> numbers1 = {1, 2, 3};
std::vector<int> numbers2 = {4, 5, 6};
auto combined = std::views::concat(numbers1, numbers2);
for (int num : doubled) {
std::cout << num << " ";
//拆分字元串
std::string text = "Hello,World,C++,Ranges";
auto splitView = text | std::views::split(',');
for (const auto& range : splitView) {
std::string token(range.begin(), range.end());
std::cout << token << std::endl;
}
//對比:
auto const ints = {0,1,2,3,4,5};
auto even = [](int i) { return 0 == i % 2; };
auto square = [](int i) { return i * i; };
// 組合視圖的“管道”語法:
for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
std::cout << i << ' ';
}
std::cout << '\n';
// 傳統的“函數式”組合語法:
for (int i : std::views::transform(std::views::filter(ints, even), square)) {
std::cout << i << ' ';
}
還有許多適配器就不一一舉例說明瞭。
高深的就不探究了,會使用好工具就得了。