为什么除了重载 + 和 - 运算符之外还必须重载 += 和 -=?

Why we must overloading += and -= beside just overloading + and - operator?

在c++中,除了重载+和-运算符,为什么还要重载+=、-=、+、-运算符?这是一个例子:

在 C++ 中,当我创建一个点 class 时,我会做:

class Point {
public:
    int x, y;
public:
    Point(int X, int Y) : x(X), y(Y) {}
    //Assignment operator
    void operator=(Point a) { x = a.x; y = a.y; }
    //The += and -= operator, this seem problematic for me. 
    void operator+=(Point a) { x += a.x; y += a.y; }
    void operator-=(Point a) { x -= a.x; y -= a.y; }
    //The + and - operator
    Point operator+(Point a) { return Point(x + a.x, y + a.y); }
    Point operator-(Point a) { return Point(x - a.x, y - a.y); }
};

但在其他一些语言中,例如 C#,我们不需要重载 += 和 -= 运算符:

public class Point {
    public int x, y;
    public Point(int X, int Y) {
        x = X; y = Y;
    }
    //We don't need to overloading =, += and -= operator in C#, all I need to do is overload + and - operator
    public static Point operator+(Point a, Point b) { return Point(a.x + b.x, a.y + b.y); }
    public static Point operator-(Point a, Point b) { return Point(a.x - b.x, a.y - b.y); }
}

并且两者都将像 c++ 一样工作!

所以我已经知道,如果我们像 C++ 一样重载,我们可以更容易地控制这个 class 可以拥有哪个运算符。但它还能做什么?

我也是c++新手,今天才学重载运算符

典型的operator+=a = a + b效率更高,不能用operator+来实现。不过也可以反过来:

struct foo {
    int value = 42;
    foo& operator+=(const foo& other) {
         this.value += other.value;
         return *this;
    }
    foo operator+(const foo& other) const {
         foo result = *this;
         result += other;   // reuse operator+=
         return result;
    }
};

请注意 operator+ 如何必须创建一个新实例,而 operator+= 只是添加现有实例的成员。

一般来说 operator+= 完全可以做其他事情,可能与 operator+ 完全无关。

同样适用于 operator-=operator-

应该问的问题是:

  1. 为什么 C# 不允许重载赋值运算符?
  2. 如果重载了“+”和“=”运算符,为什么 C++ 不能自动执行 +=?

这里讨论的第一个问题有很好的答案: TDLR;由于垃圾收集和引用计数,编译器必须确保赋值语句的左侧操作数(这是一个引用,因为在 C# class 实例是引用)在赋值期间无效,因此它的引用计数必须减少一个。如果允许 user-defined 赋值逻辑并且任何事情都可能发生在赋值运算符中,那么这种垃圾回收机制将无法工作。抱歉,这应该是 TLDR。

第二个问题的答案与定义 operator== 不会自动给你 operator!= 的原因相同,它也应该单独定义。