在 C++ 中,==(相等比较运算符)是使用频率最高的运算符之一。重载它可以让自定义类型像内置类型一样进行相等性判断。与 || 不同,== 的重载非常常见且推荐,但也有一些需要注意的规则和陷阱。
下面详细介绍 == 的重载方式、规则、注意事项,并给出简单可运行的例子。
1. 重载形式
== 是二元运算符,可以重载为成员函数或非成员函数。
成员函数
cpp
class X {
public:
bool operator==(const X& rhs) const;
};
使用时:
cpp
X a, b;
a == b; // 等价于 a.operator==(b)
非成员函数
cpp
bool operator==(const X& lhs, const X& rhs);
使用时:
cpp
X a, b;
a == b; // 等价于 operator==(a, b)
推荐使用非成员函数,因为这样可以保证左右操作数对称,并允许隐式转换同时作用于两侧。
2. 基本规则
-
不能重载两个内置类型之间的 ==,例如 bool operator==(int, int) 是非法的。
-
至少有一个操作数必须是类类型或枚举类型。
-
不能改变 == 的操作数个数、优先级和结合性。== 是二元运算符,左结合,优先级高于 &&、||,低于关系运算符。
-
返回类型通常为 bool,但 C++20 起允许返回其他类型(例如用于代理对象),不过绝大多数情况仍应返回 bool。
-
重载 == 后,a == b 会调用你的函数,而不是内置比较。
-
成员函数版本应声明为 const,因为它不修改对象。
3. 与 != 的关系
在 C++20 之前,重载了 == 不会自动获得 !=。你必须手动重载 !=,通常实现为:
cpp
bool operator!=(const X& lhs, const X& rhs) {
return !(lhs == rhs);
}
从 C++20 开始,如果重载了 ==,编译器可以自动生成 !=,其语义为 !(a == b)。这称为“重写规则”。因此 C++20 后通常只需定义 ==。
4. C++20 的三路比较与默认比较
C++20 引入了 operator<=>(三路比较),并且允许用 = default 让编译器自动生成 == 和 <=>。
使用 = default 自动生成 ==
cpp
class Point {
int x_, y_;
public:
Point(int x, int y) : x_(x), y_(y) {}
bool operator==(const Point&) const = default;
};
编译器会逐成员比较,生成正确的 == 和 !=。
使用 <=> 生成所有比较
cpp
#include <compare>
class Point {
int x_, y_;
public:
Point(int x, int y) : x_(x), y_(y) {}
auto operator<=>(const Point&) const = default;
};
这会自动生成 ==、!=、<、<=、>、>=。
5. 注意事项
对称性:a == b 和 b == a 应该得到相同结果。非成员函数更容易保证这一点。
隐式转换:如果类有隐式转换构造函数,成员函数版本可能导致 a == b 和 b == a 行为不同。C++20 的重写规则可以缓解。
const 正确性:成员函数应声明为 const,否则无法比较 const 对象。
noexcept:如果比较不会抛异常,可以标记 noexcept,有助于优化。
性能:比较可能涉及多个成员,可以先比较最可能不同的成员,或使用 std::tie 简化。
浮点数比较:如果类包含浮点数,直接 == 可能因精度问题不准确,需谨慎。
不要与赋值 = 混淆:== 是比较,= 是赋值。
继承与多态:如果类有虚函数,== 通常不应比较动态类型,除非明确需要。
#include <iostream>
class Point {
private:
int x_;
int y_;
public:
Point(int x, int y) : x_(x), y_(y) {}
// 成员函数重载 ==
bool operator==(const Point& other) const {
std::cout << "调用成员 operator==\\n";
return x_ == other.x_ && y_ == other.y_;
}
// C++17 需要手动重载 !=
bool operator!=(const Point& other) const {
std::cout << "调用成员 operator!=\\n";
return !(*this == other);
}
int x() const { return x_; }
int y() const { return y_; }
};
int main() {
Point p1(1, 2);
Point p2(1, 2);
Point p3(3, 4);
std::cout << std::boolalpha;
std::cout << "p1 == p2: " << (p1 == p2) << '\\n';
std::cout << "p1 == p3: " << (p1 == p3) << '\\n';
std::cout << "p1 != p2: " << (p1 != p2) << '\\n';
std::cout << "p1 != p3: " << (p1 != p3) << '\\n';
return 0;
}
网硕互联帮助中心





评论前必须登录!
注册