三路比较运算符operator是C++20引入的底层机制,用于让编译器自动生成全部六个比较运算符;它必须声明为const成员函数,返回std::strong_ordering等标准ordering类型,且需显式定义operator==才能启用相等比较。

三路比较运算符 operator 是什么
它不是“比大小的升级版”,而是让编译器能自动生成全部六个比较运算符(==、!=、、<code>、<code>>、>=)的底层机制。你只写一个 operator,编译器就能推导出其余逻辑——前提是类满足“一致可比较”要求,比如所有成员都支持比较。
怎么声明和定义 operator
必须是 const 成员函数,返回类型是标准库提供的三态类型:最常用的是 std::strong_ordering(值完全相等/严格小于/严格大于),也可用 std::weak_ordering(允许等价但不全等)或 std::partial_ordering(支持 NaN 这类不可比较值)。
常见写法:
struct Point {
int x, y;
auto operator<=>(const Point& other) const = default; // 编译器自动生成
};手动实现示例:
立即学习“C++免费学习笔记(深入)”;
struct Version {
int major, minor, patch;
auto operator<=>(const Version& v) const {
if (auto cmp = major <=> v.major; cmp != 0) return cmp;
if (auto cmp = minor <=> v.minor; cmp != 0) return cmp;
return patch <=> v.patch;
}
};-
= default仅在所有数据成员都可比较且顺序即为期望顺序时安全 - 手动实现中,用
if (auto cmp = ...; cmp != 0) return cmp;是惯用模式,避免嵌套 - 不要返回
int或自定义枚举——必须返回标准 ordering 类型,否则无法触发自动生成其他比较符
为什么 == 还要单独写?
默认情况下,operator 不会生成 operator==;C++20 要求显式控制相等语义。但你可以用 default 让编译器生成它:
struct Data {
std::string name;
int id;
bool operator==(const Data& other) const = default; // 必须显式声明
auto operator<=>(const Data& other) const = default;
};- 没写
operator==,哪怕有operator,a == b也会编译失败 - 如果写了自定义
operator==,就不能再对operator使用= default(冲突) -
operator==和operator可以独立实现,语义不必完全一致(比如 == 比较逻辑值, 比较存储布局)
容易踩的坑
最常被忽略的是隐式转换干扰和返回类型错误:
- 若类有非 explicit 构造函数(如
String(const char*)),"hello" s可能意外触发转换,导致调用错误重载——加explicit或禁用无关构造函数 - 返回
int(如return x - y;)会导致编译通过但失去三路语义,==等不会自动生成,且可能整数溢出 - 使用
std::strong_ordering::equal等字面量手动返回?别这么干——直接用表达式,它自动推导正确值 - 继承体系中,基类有
operator,派生类想扩展比较字段时,不能只靠= default,得手动调用基类比较并拼接字段
真正麻烦的从来不是写法,而是搞清你到底需要“强序”“弱序”还是“偏序”——这取决于你的数据是否允许 NaN、是否区分大小写等语义细节。


















