云计算百科
云计算领域专业知识百科平台

深入理解C++ 重载 <二十>==运算符

在 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;
    }

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 深入理解C++ 重载 <二十>==运算符
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!