当类成员均支持比较且语义符合字典序时,应优先使用 operator 配合 = default;否则需手写各比较运算符以自定义逻辑。

直接用 operator 声明三路比较运算符,配合 = default 让编译器自动生成,是 C++20 中最安全、最简洁的实现方式——前提是类成员都支持比较,且语义符合“字典序”逻辑。
什么时候该用 operator 而不是手写 operator 等?
当你需要完整定义 、、==、!=、>、>= 全套比较关系,且各成员天然可比(如 int、std::string、其他已支持 的类型)时,operator 是首选。它避免了手写多个运算符时漏掉某个、或逻辑不一致的问题。
常见错误现象:只重载 operator,却忘了 operator==,导致 std::set 或 std::sort 行为异常;或手写多个运算符时,a 和 !(b 不等价。
- 若类只有简单 POD 成员(如
int x; std::string name;),默认三路比较完全够用 - 若需自定义比较逻辑(如忽略大小写、按权重排序),则必须手动定义
operator,不能= default - 若类含不可比较成员(如
std::unique_ptr、函数指针),= default会编译失败,需显式处理
operator 的返回类型和语义怎么选?
返回类型决定比较粒度:std::strong_ordering(完全可排序,如数字)、std::weak_ordering(等价但不全等,如忽略大小写的字符串)、std::partial_ordering(可能无序,如浮点数含 NaN)。选错会导致 static_assert 失败或运行时行为不符合预期。
立即学习“C++免费学习笔记(深入)”;
使用场景:绝大多数自定义结构体应返回 std::strong_ordering;若两个对象“逻辑相等”但二进制不同(比如字符串比较忽略大小写),用 std::weak_ordering;仅当确实需要处理未定义序(如含 float 字段且允许 NaN)才用 partial_ordering。
-
std::strong_ordering:要求a == b当且仅当所有字段逐位相等 -
std::weak_ordering:允许a b == 0但a != b(例如"A"和"a") - 返回
std::partial_ordering::unordered会令std::sort报错,慎用
手写 operator 时如何组合多个成员?
别自己写嵌套 if 判断,用 std::tie 或 C++20 的 std::compare_weak_order_fallback 风格组合。核心原则:从左到右依次比较,任一成员不等就立刻返回,后续成员不再检查。
性能影响:std::tie(a, b, c) std::tie(other.a, other.b, other.c) 生成的代码和手写 if-else 几乎一致,无额外开销;但注意 std::tie 会隐式转换为 std::tuple,若成员类型不支持 ,编译失败。
struct Person {
std::string name;
int age;
// 手动实现:按 name 升序,name 相同时按 age 降序
auto operator<=>(const Person& other) const {
if (auto cmp = name <=> other.name; cmp != 0) return cmp;
return other.age <=> age; // 注意:age 降序 → other.age 在前
}
};
- 优先用链式比较:
if (auto cmp = a b; cmp != 0) return cmp;,清晰且易调试 - 避免
return (name other.name) ?: (age other.age);——?:在 C++20 中对ordering类型不适用,编译不过 - 若成员本身返回
std::partial_ordering(如float),整个结果也得是partial_ordering,否则类型不匹配
兼容旧代码和容器时要注意什么?
即使你只定义了 operator,C++20 编译器也会自动合成 operator==(如果没显式定义),但 operator 等不会自动合成——除非你用 friend bool operator 显式委托。
容易被忽略的地方:STL 容器如 std::map 默认用 std::less,它内部调用 ,而不是 。所以仅提供 不足以让 std::map 正常工作,除非你额外提供 operator 或特化 std::less。
- 最省事方案:定义
operator+operator==(哪怕= default),再加一个friend bool operator b) - 不要依赖编译器自动合成
operator:C++20 标准并未规定它会合成,目前主流编译器(GCC/Clang)都不合成 - 若用
std::vector配合std::sort,只要提供了operator 或传入自定义比较器即可,本身不参与
真正麻烦的从来不是写对一个 operator,而是确保它和已有接口(尤其是 STL 容器模板参数、泛型算法)的交互方式符合直觉——多花一分钟检查 std::map 是否能编译通过,比上线后查半天 segmentation fault 强得多。










