std::lexicographical_compare 是按字典序逐元素比较两个迭代器范围的算法,返回 true 当且仅当前一范围字典序小于后一范围,适用于任意可比较类型的容器或数组。

std::lexicographical_compare 是什么,它比较的是什么
std::lexicographical_compare 不是比较两个容器对象本身的地址或大小,而是逐元素按字典序(类似字典里单词排序)比较两个**范围**(通常是迭代器对)。它返回 true 当且仅当前一个范围“在字典序上小于”后一个范围。这和 std::string 的 operator 行为一致,但泛化到了任意可比较的元素类型和任意迭代器范围。
关键点:它不关心容器类型,只关心传入的迭代器对(first1, last1 和 first2, last2),因此可用于 std::vector、std::array、std::list、C 风格数组,甚至自定义迭代器范围。
基本用法与常见错误写法
正确调用必须保证迭代器有效且成对匹配。最常踩的坑是传错 end() 迭代器或混用不同容器的迭代器。
- ✅ 正确:比较两个
std::vector的全部内容
std::vectora = {1, 2, 3}; std::vector b = {1, 2, 4}; bool result = std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); // true
- ❌ 错误:用
b.end()去比a的范围(越界未定义行为)
// 危险!b.end() 可能指向 a 范围外,且语义完全错误 std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); // ✅ 正确写法如上 // std::lexicographical_compare(a.begin(), a.end(), b.begin(), a.end()); // ❌ 混用
- ⚠️ 注意:空范围永远“小于”非空范围;两个空范围相等,故返回
false
自定义比较函数与字符串忽略大小写的场景
默认使用 operator,但可通过第 5 个参数传入二元谓词。典型应用是忽略大小写的字符串比较(注意:不是用 std::string::compare,而是对 char 级别做处理)。
立即学习“C++免费学习笔记(深入)”;
例如:
- 用
std::tolower(需注意 locale,简单 ASCII 场景可用) - 避免直接传
std::tolower函数指针——它有重载,编译器无法推导 - 应包装为 lambda 或函数对象
std::string s1 = "Hello";
std::string s2 = "HELLO";
bool ignore_case = std::lexicographical_compare(
s1.begin(), s1.end(),
s2.begin(), s2.end(),
[](unsigned char a, unsigned char b) {
return std::tolower(a) < std::tolower(b);
}
); // false —— 因为 "Hello" 和 "HELLO" 字典序相等(忽略大小写)
性能与替代方案:什么时候不该用它
std::lexicographical_compare 是线性时间复杂度 O(min(len1, len2)),没有额外空间开销,这点很好。但它不适用于以下情况:
- 你其实只想知道“是否相等”——此时用
std::equal更语义清晰,且部分实现可能早停优化 - 你在比较
std::string且不需要自定义逻辑——直接用s1 ,更简洁、可读性高、且可能被编译器内联优化得更好 - 你正在比较
std::vector且T本身已支持operator——仍可用,但若频繁调用,建议确认是否真需要字典序语义(比如排序 key),而非误以为这是“容器比较唯一方式”
最容易被忽略的一点:它不提供三路比较结果(小于 / 等于 / 大于),只返回 bool。如果后续还需判断“大于”,不能简单取反——因为两范围可能既不小于也不大于(即相等),得另行调用一次反向比较或改用 std::lexicographical_compare_three_way(C++20)。











