std::sort是C++11起<algorithm>中基于随机访问迭代器的泛型排序函数,默认升序、平均O(n log n),支持lambda/函数指针/functor自定义比较,要求严格弱序,不保证稳定,注意迭代器失效与捕获安全。

sort 函数的基本调用形式(C++11 及以后)
std::sort 是 <algorithm></algorithm> 头文件提供的泛型排序函数,要求容器支持随机访问迭代器(如 std::vector、std::array、原生数组)。它默认按升序排列,底层是 introsort(堆 + 快 + 插入混合),平均时间复杂度 O(n log n)。
最常用写法:
std::vector<int> v = {3, 1, 4, 1, 5};
std::sort(v.begin(), v.end()); // 升序:{1, 1, 3, 4, 5}
注意:v.begin() 和 v.end() 是左闭右开区间,v.end() 不参与排序 —— 这点写错会导致未定义行为。
用 lambda 表达式实现降序或复合排序
自定义排序最常用方式是传入第三个参数:一个可调用对象(lambda、函数指针、functor)。它必须接受两个同类型参数,返回 bool,语义为“第一个参数是否应排在第二个之前”(即 strict weak ordering)。
立即学习“C++免费学习笔记(深入)”;
- 降序排列
int向量:std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); - 按字符串长度排序:
std::vector<std::string> words = {"hi", "hello", "a"}; std::sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) { return a.length() < b.length(); }); // {"a", "hi", "hello"} - 结构体多级排序(先按
score降序,相等时按name升序):struct Student { std::string name; int score; }; std::vector<Student> students = {{"Alice", 85}, {"Bob", 92}, {"Charlie", 92}}; std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) { if (a.score != b.score) return a.score > b.score; return a.name < b.name; });
⚠️ 常见错误:lambda 捕获了局部变量但没声明引用([&]),或对非 const 对象做了修改;返回值不是严格弱序(比如用 替代 <code>),会触发 <code>std::sort 断言失败或崩溃。
用函数指针或仿函数(functor)替代 lambda
当排序逻辑复用频繁、或需保持状态时,函数指针或 functor 更合适。注意函数签名必须匹配:bool(Args...),且不能是重载函数名(编译器无法推导)。
函数指针示例:
bool cmp_desc(int a, int b) { return a > b; }
std::sort(v.begin(), v.end(), cmp_desc);
Functor 示例(带状态的比较器):
struct ByMod {
int mod;
ByMod(int m) : mod(m) {}
bool operator()(int a, int b) const {
return (a % mod) < (b % mod);
}
};
std::sort(v.begin(), v.end(), ByMod(3)); // 按模 3 的余数升序
⚠️ functor 必须定义 operator() 为 const 成员函数,否则 std::sort 内部可能因临时拷贝导致调用失败。
注意事项:稳定性、迭代器失效与自定义类型
std::sort 是不稳定的(相同元素相对顺序可能改变);如需稳定排序,改用 std::stable_sort。
- 排序过程中,容器内元素会被移动/交换,因此所有指向这些元素的原始指针、引用、迭代器(除用于调用的
begin/end)全部失效 —— 别在排序后继续用它们访问数据。 - 自定义类型必须提供可比较的字段,且比较逻辑不能依赖未初始化成员或外部全局状态(否则排序结果不可预测)。
- 对
std::list或std::forward_list,不能直接用std::sort(不满足随机访问),应改用其成员函数sort()。
真正容易被忽略的是:lambda 捕获列表和参数 const 引用的组合——尤其处理大对象时,漏掉 const& 会导致不必要的拷贝;而过度捕获(比如 [=] 捕获整个 vector)可能引发悬垂引用。










