以下是關于 ranges::sort() 的詳細說明:
1. ranges::sort() 的使用方法
ranges::sort()
是 C++20
引入的基于范圍(Ranges)的排序函數,其語法更簡潔,支持直接操作容器或范圍對象。
(1)基本用法
#include <vector>
#include <ranges>
#include <algorithm>int main() {std::vector<int> numbers = {3, 1, 4, 1, 5};std::ranges::sort(numbers); // 直接對容器排序return 0;
}
(2)逆序排序
通過傳遞 std::greater<>
實現降序:
std::ranges::sort(numbers, std::greater<>());
(3)自定義排序規則
使用 Lambda
表達式或自定義比較函數:
std::ranges::sort(numbers, [](int a, int b) {return a % 3 < b % 3; // 按模3的余數排序
});
2. 相比于傳統 std::sort 的優勢
(1) 更簡潔的語法
傳統 std::sort
需要手動指定迭代器范圍:
std::sort(numbers.begin(), numbers.end());
ranges::sort
直接操作容器,省去迭代器:
std::ranges::sort(numbers); // 無需 begin/end
(2) 支持范圍概念(Concepts)
ranges::sort
在編譯期通過概念(Concepts)檢查參數合法性,錯誤提示更清晰。例如,若元素類型不支持比較,編譯器會直接報錯。
(3) 與范圍庫的無縫結合
可與其他范圍適配器(如視圖 views
)結合使用,實現鏈式操作:
// 過濾偶數后排序
auto filtered = numbers | std::views::filter([](int x) { return x % 2 == 0; });
std::ranges::sort(filtered);
(4) 性能優化
對大型數據集可能有性能優化,因底層實現可能采用更高效的策略。
3. 使用注意點
(1) C++20 兼容性
需確保編譯器支持 C++20 標準(如 GCC 10+、Clang 13+、MSVC 19.29+)。
(2) 元素類型需支持比較
元素類型必須定義 < 運算符或提供自定義比較函數。否則編譯失敗。
(3) 比較函數的嚴格弱序
自定義比較函數需滿足嚴格弱序(Strict Weak Ordering),否則行為未定義。
(4) 視圖的惰性計算
若對視圖(如 views::filter 結果)調用 ranges::sort,需注意視圖可能是惰性計算的,可能導致意外結果3。
總結
ranges::sort
通過簡化語法、增強類型安全和優化性能,成為 C++20 中更現代的排序選擇。在支持 C++20 的項目中優先使用,可提升代碼可讀性和健壯性。傳統 std::sort 仍適用于舊代碼或低版本編譯器環境。
4. 實際分析
看靈神的代碼的時候發現一個排序是這樣寫的:
vector<vector<int>> queries;
//...
ranges::sort(queries, {}, [](auto& q) { return q[0]; });
這段代碼的作用是對二維向量 queries
按每行第一個元素(即 q
)進行升序排序。以下是詳細分析:
4.1 代碼解析
ranges::sort(queries, {}, [](auto& q) { return q; });
-
參數含義:
queries
:待排序的二維向量(vector<vector<int>>
)。{}
:占位符,表示使用默認比較規則(std::less
,即升序)。[](auto& q) { return q; }
:投影函數(Projection),指定排序依據為每行的第一個元素q
。
-
等效傳統寫法(使用
std::sort
):std::sort(queries.begin(), queries.end(), [](const auto& a, const auto& b) {return a < b; });
4.2 優勢:ranges::sort 的簡潔性
- 直接操作容器:無需手動傳遞
begin/end
迭代器(傳統寫法需queries.begin(), queries.end()
)。 - 投影函數:通過
[](auto& q) { return q; }
直接指定排序字段,避免了在比較函數中重復提取a
和b
,代碼更簡潔。 - 類型安全:C++20 的
ranges::sort
通過概念(Concepts)檢查參數合法性,確保投影后的值可比較。
3. 注意點
- 子向量非空:必須確保每行子向量至少有一個元素,否則
q
會導致未定義行為(如越界訪問)。 - 嚴格弱序:默認使用
std::less
升序排序,若需降序,需顯式傳遞std::greater{}
作為第二個參數:ranges::sort(queries, std::greater{}, [](auto& q) { return q; });
- 兼容性:需編譯器支持 C++20(如 GCC 10+、Clang 13+)。
4. 與傳統 std::sort 的對比
特性 | ranges::sort | 傳統 std::sort |
---|---|---|
語法簡潔性 | 直接操作容器,無需迭代器 | 需手動傳遞 begin/end 迭代器 |
投影函數 | 支持,簡化字段提取邏輯 | 需在比較函數中顯式提取字段 |
類型檢查 | 編譯期概念檢查,錯誤提示更友好 | 運行時可能因類型錯誤崩潰 |
總結
這段代碼利用 C++20 的 ranges::sort
對二維向量按首元素升序排序,通過投影函數簡化了邏輯,是更現代的寫法。注意確保子向量非空,并根據需求調整升/降序規則。在支持 C++20 的項目中推薦優先使用 ranges::sort
。