C++20 引入了三向比较运算符(<=>),也被称为“spaceship”运算符,它能简化排序、比较以及自定义类型的比较逻辑。本文从基础语法、自动生成比较器、以及与 STL 容器的协作等方面,系统阐述如何高效地利用三向比较运算符。
1. 基础语法
三向比较运算符返回 std::strong_ordering、std::weak_ordering 或 std::partial_ordering,其枚举值分别对应 <、==、>。示例:
#include <compare>
int main() {
int a = 5, b = 7;
if (a <=> b == std::strong_ordering::less) { /* … */ }
}
若仅需要标准的 <, ==, >,可以直接使用 return a <=> b;。
2. 自动生成比较器
C++20 提供 std::strong_ordering operator<=>(const X&, const X&) = default;,只要结构体或类满足以下条件即可自动生成比较函数:
- 所有成员均可比较(支持
<=>或==)。 - 需要排序的成员顺序与定义顺序一致。
struct Point {
int x, y;
auto operator<=>(const Point&) const = default;
};
这样 Point{1,2} < Point{1,3} 将基于 x 再 y 进行比较。
3. 与 STL 容器协作
std::map、std::set 等容器默认使用 std::less,它内部会调用 <=>,因此若你的类型实现了三向比较运算符,插入、查找、排序将更加直观。
std::set <Point> s;
s.insert({2,3});
s.insert({1,5});
此处 set 会自动按 x 再 y 排序。
4. 与自定义排序函数的融合
有时需要对某些成员或属性进行自定义排序。可以通过 std::tie 与三向比较结合:
struct Employee {
std::string name;
double salary;
auto operator<=>(const Employee& other) const {
return std::tie(salary, name) <=> std::tie(other.salary, other.name);
}
};
这里先按薪资比较,薪资相等时再按姓名。
5. 性能与可读性
- 可读性提升:代码中可直接看到比较结果,无需拆分
if-else。 - 性能:编译器可针对
operator<=>生成更高效的比较序列,尤其在多成员比较时避免多次访问。
6. 常见坑
- 不支持所有类型:若成员类型没有
<=>,编译会报错,需要手动提供==并使用std::partial_ordering或std::weak_ordering。 - 复合类型:
std::vector、std::array只在 C++20 之后才支持<=>,使用时需确认编译器已开启 C++20。
7. 小结
三向比较运算符让 C++ 的比较逻辑更简洁、强大。通过默认实现、std::tie 组合以及与 STL 的无缝集成,可以让我们的代码既易于维护,又能获得编译器级的优化。只要在定义类时添加 auto operator<=>(const X&) const = default; 或自定义比较逻辑,即可享受到三向比较带来的便利。