std::ranges::stable_sort需包含且仅c++20起可用,只接受random_access_range(如vector、deque、数组),不支持list等;默认升序原地排序,支持投影和自定义比较器,稳定性由算法保证。

std::ranges::stable_sort 的基本用法和必要头文件
必须包含 <algorithm></algorithm>,且 C++20 起才可用。它不接受原始指针区间(如 arr, arr + n),只接受范围(range)——比如容器、视图或带 begin()/end() 的自定义类型。
最常见写法是直接传容器:
std::vector<int> v = {3, 1, 4, 1, 5};<br>std::ranges::stable_sort(v);</int>
- 默认按
operator 升序排序 - 原地修改,不返回新容器
- 不支持像
std::sort那样传两个迭代器;若需部分排序,得先用视图切片,例如std::ranges::subrange(v.begin() + 2, v.end())
自定义比较函数时的参数顺序和约束
与 std::stable_sort 不同,std::ranges::stable_sort 的比较函数(谓词)接收的是元素值本身,不是迭代器解引用后的结果 —— 这点容易写错。
错误写法(拿迭代器当参数):[](auto it1, auto it2) { return *it1 → 编译失败
正确写法:
std::vector<:string> words = {"apple", "Banana", "cherry"};<br>std::ranges::stable_sort(words, [](const auto& a, const auto& b) {<br> return a.size() });</:string>
- 谓词参数类型必须能绑定到容器元素类型(通常加
const auto&最安全) - 不能返回
void,必须返回可转换为bool的值 - 若用
std::less等标准函数对象,需显式指定模板参数,如std::ranges::stable_sort(v, std::less<int>{})</int>
与 std::stable_sort 的关键差异:不支持随机访问迭代器以外的范围
std::ranges::stable_sort 内部要求底层迭代器满足 random_access_iterator 概念,否则编译失败。这意味着:
-
std::list、std::forward_list不能直接传入 —— 即使它们有begin()/end(),也不满足随机访问 -
std::vector、std::deque、原生数组、std::array都可以 - 某些视图(如
std::views::filter)生成的范围通常不是随机访问的,也不能直接排序
想对 std::list 稳定排序?只能用传统接口:lst.sort()(成员函数)或 std::stable_sort(lst.begin(), lst.end())。
性能和稳定性保障的实际含义
“稳定”指相等元素的相对顺序不变 —— 这在处理含多个字段的数据时很关键,比如先按分数排序,再按姓名稳定排序,能保留同分者原有的输入顺序。
但要注意:
- 它不保证算法具体实现(通常是归并类),时间复杂度仍是
O(n log n),空间复杂度一般为O(n) - 若容器元素移动代价高(如大对象),
std::ranges::stable_sort会尽量用移动而非拷贝,但前提是类型满足movable概念 - 没有“就地归并”的优化路径;哪怕容器是
std::vector且已预留足够空间,它仍可能额外分配内存
真正容易被忽略的是:当你把一个视图(比如 std::views::take)传给 std::ranges::stable_sort,它不会报运行时错,而是在编译期因概念检查失败直接拒掉 —— 错误信息往往很长,重点盯住 “constraints not satisfied” 和 “random_access_iterator” 这几个词。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











