std::lexicographical_compare 是按字典序逐元素比较两个迭代器范围的算法,返回 true 当且仅当前一范围字典序小于后一范围,适用于任意可比较类型的容器或数组。
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 级别做处理)。
例如:
std::tolower(需注意 locale,简单 ASCII 场景可用)std::tolower 函数指针——它有重载,编译器无法推导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)。