最直接标准做法是将字符串存入std::vector后用std::sort配合按长度比较的lambda;C++原生数组需手动传首尾指针,易出错如漏写const auto&导致拷贝开销。

用 std::sort 配合 lambda 比较函数最直接
标准做法是把字符串存进 std::vector<:string></:string>,然后调用 std::sort 并传入一个按长度比较的 lambda。C++ 原生数组(如 std::string arr[5])也能排,但得手动传入首尾指针,不如 vector 直观安全。
常见错误是写成 sort(arr, arr + n, [](auto a, auto b) { return a.size() 却忘了加 <code>const&——尤其字符串较长时,值传递会频繁拷贝,拖慢速度甚至触发临时对象构造开销。
- 推荐写法:
[](const std::string& a, const std::string& b) { return a.length() -
length()和size()在std::string中完全等价,任选其一即可 - 如果字符串来自 C 风格数组(
char*[]),得先转成std::string或用strlen比较,不能直接用.size()
原始字符数组(char*[])怎么安全排序
如果你手头是 char* strs[4] = {"hello", "a", "world", "hi"}; 这种,std::sort 仍可用,但比较逻辑必须用 std::strlen,且注意空指针风险。
典型翻车点:没检查 strs[i] 是否为 nullptr,一调 strlen(nullptr) 就崩溃;或者误用 sizeof(strs[i])——那得到的是指针大小(通常是 8),不是字符串长度。
立即学习“C++免费学习笔记(深入)”;
- 安全比较 lambda:
[](const char* a, const char* b) { return (a ? strlen(a) : 0) - 排序后原指针数组元素顺序改变,但每个字符串字面量内存位置不变,无需深拷贝
- 若需修改字符串内容,务必确保它们存于可写内存(比如用
new char[]分配或std::vector<char></char>管理)
自定义结构体里含字符串,按其长度排序
当字符串是结构体成员(如 struct Item { std::string name; int id; };),排序目标其实是整个结构体数组,但依据是 name.length()。
这时候容易漏掉 const 正确性:如果结构体较大,比较函数参数不加 const&,每次比较都会拷贝整个结构体,性能断崖式下跌。
- 正确写法:
[](const Item& x, const Item& y) { return x.name.length() - 如果结构体有移动语义且你想避免冗余拷贝,lambda 参数类型保持
const&即可,std::sort内部移动操作不受影响 - 别在比较函数里调
std::string::c_str()再算长度——绕路且无必要
排序稳定性会影响相同长度字符串的相对顺序吗
std::sort 是非稳定排序(不稳定意味着相同长度的字符串可能重排),如果你需要保持原始顺序(比如“cat”和“dog”都长 3,希望“cat”始终在前),就得换用 std::stable_sort。
代价是:稳定排序通常比普通 sort 多耗一点时间和空间(比如额外 O(n) 内存)。实际项目中,除非业务明确要求“同长则按输入顺序”,否则默认用 std::sort 更高效。
- 启用稳定排序只需把
std::sort换成std::stable_sort,其余代码完全不变 - 没有“长度相同时按字典序再排”的需求?就别在比较函数里多加
|| a ——这会掩盖你真实意图,也增加分支预测失败概率
真正容易被忽略的是字符串来源:从文件读、用户输入、网络接收来的字符串,可能含空字符或编码异常,.length() 依然可靠,但如果你误以为它在统计“可见字符数”(比如 UTF-8 中的汉字占多个字节),那就踩进编码坑了——std::string::length() 返回的是字节数,不是 Unicode 码点数。


















