std::sort要求随机访问迭代器,原生数组需传arr和arr+n(末尾后位置),推荐std::sort(std::begin(arr), std::end(arr))或vector的v.begin()/v.end()。

std::sort 要求传入随机访问迭代器,原生数组不能直接传数组名
很多人写 std::sort(arr, arr + n) 看似正确,但实际能编译通过只是因为数组名会隐式退化为指针——而 int* 恰好满足随机访问迭代器的要求。这不是“支持数组”,而是“碰巧指针符合要求”。真正要注意的是:必须确保第二个参数指向**末尾之后的位置**(即 arr + n),不是 arr + n - 1,否则排序范围少一个元素。
常见错误现象:std::sort(arr, arr + n - 1) 导致最后一个元素永远不参与排序;或传 arr 和 &arr[n] 却忘了 &arr[n] 是合法的(只要 n >= 0)。
- 推荐写法:
std::sort(arr, arr + n)(最直观) - 更安全的替代:
std::sort(std::begin(arr), std::end(arr))(仅当arr是栈上固定大小数组,且未退化为指针) - 若用
std::vector,直接std::sort(v.begin(), v.end())
自定义比较函数时,lambda 必须是可调用对象且捕获要谨慎
排序降序写 std::sort(arr, arr + n, [](int a, int b) { return a > b; }) 没问题;但若 lambda 捕获局部变量(比如 [&x](int a, int b) { return a ),会导致编译失败——因为 <code>std::sort 内部可能复制该 callable,而带引用捕获的 lambda 不可复制(C++11 起禁止)。即使编译通过,运行时行为也可能未定义。
- 安全做法:只用值捕获(
[=])或无捕获 lambda([]) - 若需外部数据,优先传入普通函数指针或静态成员函数
- 避免在比较函数中修改参数、全局状态或抛异常——
std::sort要求比较函数是 strict weak ordering 且无副作用
std::sort 不稳定,相同元素的相对位置可能改变
如果业务逻辑依赖相等元素的原始顺序(比如先按分数排,分数相同时保持录入顺序),std::sort 不能保证这点。它底层通常是 introsort(快排+堆排+插排混合),本质不稳定。
立即学习“C++免费学习笔记(深入)”;
- 改用
std::stable_sort,时间复杂度略高(平均 O(n log²n)),但保证稳定性 - 或手动扩展 key:把原始下标打包进结构体,排序时用
{value, index}作为复合 key - 注意:
std::stable_sort对原生数组同样适用:std::stable_sort(arr, arr + n)
对 char 数组或字符串字面量排序要小心类型和所有权
写 char s[] = "hello"; std::sort(s, s + 5); 可以,因为 s 是可修改的栈数组;但 const char* s = "hello"; std::sort(s, s + 5); 编译失败——const char* 迭代器解引用是 const char&,无法写入。
更隐蔽的坑:std::sort("hello", "hello" + 5) 直接 UB,因为字符串字面量存于只读段,尝试修改会触发段错误(SIGSEGV)。
- 永远不要对字符串字面量(
"abc")或const char*指向的内存调用std::sort - 需要排序字符串内容时,用
std::string或栈上char buf[...] - 若处理 C 风格字符串,确保目标内存可写且以
\0结尾不影响排序逻辑(std::sort不关心是否是 C 字符串)
标准库没义务替你检查内存可写性或迭代器有效性。越简洁的调用(比如 std::sort(a, a+n)),背后越依赖你对数组生命周期、可写性和边界的准确判断。


















