C++20三路比较运算符()可统一定义比较逻辑并自动生成六个关系运算符;默认实现用= default,手动实现推荐std::tie逐字段比较;需注意语义一致性、指针安全及模板约束。

三路比较运算符(,又称“太空船运算符”)是 C++20 引入的核心特性,用于统一、简洁地定义类型的比较逻辑。它让编译器能自动合成 ==、!=、、、>、>= 六个关系运算符,大幅减少样板代码。
声明和默认实现
只需在类中声明一个 operator 成员函数(或非成员函数),并返回标准比较类别类型(如 std::strong_ordering),编译器就能自动生成其余比较操作:
- 返回
std::strong_ordering:要求值完全可比较且无等价但不相等的情况(适合普通聚合类型) - 返回
std::weak_ordering:允许等价(a b == 0)但a != b(如忽略大小写的字符串) - 返回
std::partial_ordering:支持 NaN 等不可比较值(如浮点数)
最常用的是 std::strong_ordering。启用默认行为只需写:auto operator(const MyClass&) const = default;
前提是所有成员都支持三路比较且可默认构造/复制。
手动实现常见模式
当需要自定义逻辑(比如按优先级比较多个字段),推荐用 std::tie 或 std::tuple 逐字段比较:
- 使用
std::tie(a, b, c) std::tie(other.a, other.b, other.c)—— 简洁、高效、语义清晰 - 字段类型不支持
?需先确保它们已定义或为内置类型(int、string 等均已支持) - 避免手写嵌套
if判断:易出错且难以维护,std::tie自动按左到右顺序短路比较
例如:auto operator<=>(const Person& p) const {
return std::tie(age, name) <=> std::tie(p.age, p.name);
}
与相等运算符的关系
C++20 中,若只定义了 operator,编译器会自动生成 operator==(基于 返回是否为 0),但该默认 == 是“一致的相等”,不是“强相等”。如果类型语义上需要更精确的相等判断(比如忽略空格或默认值),应显式定义 operator==,此时编译器将不再合成它。
立即学习“C++免费学习笔记(深入)”;
- 显式定义
operator==→ 优先使用它,不影响== - 只定义
operator→ 自动生成==和全部关系运算符 - 两者都不定义 → 无比较能力(除非基类提供)
注意事项和限制
三路比较不是万能的:
- 不能重载为非成员函数同时参与 ADL(除非在类内部声明为 friend)
- 若类有指针或自定义资源,
= default可能不安全,需手动实现 - 模板类中使用
= default要求所有模板参数满足三路比较约束 - 继承体系中,基类未定义
时,派生类无法靠= default自动比较基类部分
调试时可直接输出 obj1 obj2 的结果:它是枚举值(std::strong_ordering::less、::equal、::greater),可直接用于 switch 或条件判断。










