为什么除了重载 + 和 - 运算符之外还必须重载 += 和 -=?
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-
。
应该问的问题是:
- 为什么 C# 不允许重载赋值运算符?
- 如果重载了“+”和“=”运算符,为什么 C++ 不能自动执行 +=?
这里讨论的第一个问题有很好的答案:
TDLR;由于垃圾收集和引用计数,编译器必须确保赋值语句的左侧操作数(这是一个引用,因为在 C# class 实例是引用)在赋值期间无效,因此它的引用计数必须减少一个。如果允许 user-defined 赋值逻辑并且任何事情都可能发生在赋值运算符中,那么这种垃圾回收机制将无法工作。抱歉,这应该是 TLDR。
第二个问题的答案与定义 operator== 不会自动给你 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-
。
应该问的问题是:
- 为什么 C# 不允许重载赋值运算符?
- 如果重载了“+”和“=”运算符,为什么 C++ 不能自动执行 +=?
这里讨论的第一个问题有很好的答案: TDLR;由于垃圾收集和引用计数,编译器必须确保赋值语句的左侧操作数(这是一个引用,因为在 C# class 实例是引用)在赋值期间无效,因此它的引用计数必须减少一个。如果允许 user-defined 赋值逻辑并且任何事情都可能发生在赋值运算符中,那么这种垃圾回收机制将无法工作。抱歉,这应该是 TLDR。
第二个问题的答案与定义 operator== 不会自动给你 operator!= 的原因相同,它也应该单独定义。