std::sort自定义比较器需为可调用对象且参数为const引用,常见错误是捕获变量未加[&]或[=]、参数非const导致编译失败。

std::sort 里传自定义比较器最常用也最容易出错
直接用 std::sort 对原生数组排序时,比较器必须是可调用对象(函数指针、lambda 或仿函数),且签名得是 bool( const T&, const T& )。常见错误是捕获局部变量却忘了加 [&] 或 [=],或者把参数写成非 const 引用导致编译失败。
比如对 int 数组按绝对值升序排:
int arr[] = {-3, 1, -5, 2};
int n = 4;
std::sort(arr, arr + n, [](int a, int b) { return std::abs(a)
- lambda 必须捕获外部变量才可用(如需要访问某个阈值),否则直接写表达式就行
- 不能写成
(int& a, int& b)——std::sort内部可能传临时量,非常量引用会编译报错 - 数组名退化为指针,所以要用
arr + n表示右边界,不是&arr[n](虽等价但易混淆)
用函数指针做比较器要注意声明位置和链接性
全局函数或 static 函数可以直接取地址传给 std::sort;非 static 成员函数不行,因为隐含 this 参数。如果硬要用类内逻辑,得提出来做成自由函数或 static 成员。
例如想按字符串长度排序 char* 数组:
bool cmp_by_len(const char* a, const char* b) {
return std::strlen(a)
- 函数必须在调用前声明或定义,否则链接时报
undefined reference - 如果放在类里,只能用
static bool cmp(...),然后传&MyClass::cmp - 避免返回
std::string::size()这类无符号类型比较结果,容易因隐式转换翻车
对结构体数组排序时,比较器字段访问要明确
结构体字段如果是 private,比较器无法直接访问;public 字段或提供 public getter 才行。另外,字段类型影响比较逻辑是否合法 —— 比如 float 字段用 比较可能因精度问题违反严格弱序。
struct Person {
std::string name;
int age;
};
Person people[] = {{"Alice", 30}, {"Bob", 25}};
std::sort(people, people + 2, [](const Person& a, const Person& b) {
return a.age
- 若
age是 private,得写a.get_age() ,且 <code>get_age()要是 const 成员函数 - 多个字段排序(如先按 age 升序,age 相同按 name 字典序):用
return a.age != b.age ? a.age - 不要在比较器里做耗时操作(如打开文件、网络请求),
std::sort可能调用几十次
原生数组和 std::array 的比较器用法有细微差别
std::array 是容器,支持 .begin()/.end(),传参更统一;原生数组靠指针算术。但两者都接受完全相同的比较器类型 —— 不需要为其中一种重写逻辑。
std::array<int> arr = {-3, 1, -5, 2};
std::sort(arr.begin(), arr.end(), [](int a, int b) { return std::abs(a) <ul>
<li>别对 <code>std::array</code> 写 <code>&arr[0]</code> 来获取首地址 —— 虽然可行,但绕过接口,失去类型安全</li>
<li>如果数组大小在编译期未知(比如函数参数是 <code>int arr[]</code>),就只能用指针方式,无法用 <code>std::array</code>
</li>
<li>模板参数推导有时会卡住,比如 lambda 捕获了模板参数,这时显式写 <code>std::sort<decltype>(...)</decltype></code> 很麻烦,不如老实用指针</li>
</ul>
<p>C++ 数组排序本身不难,但比较器一旦涉及生命周期(lambda 捕获)、访问控制(private 字段)、数值精度(float 比较)或类型推导(模板上下文),就很容易静默出错或行为异常。动手前先确认比较逻辑满足严格弱序,再检查参数 const 正确性和调用方式匹配性。</p></int>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











