+= 运算符是如何在 C++ 中实现的?

How has += operator been implemented in c++?

这是一个我一直在思考的问题,但从未找到任何资源来说明这个问题的答案。事实上,它不仅适用于 +=,还适用于它的兄弟姐妹,即 -=*=/= 等(当然不是 ==)。

考虑这个例子,

int a = 5;
a += 4;
//this will make 'a' 9

现在考虑等效表达式:

a = a + 4;
//This also makes 'a' 9

如果 += 只是 a = a + <rhs of +=> 的 shorthand 重载 + 运算符也应隐式重载 +=,除非以其他方式显式重载。但事实并非如此。这意味着,a += b 不会转换为 a = a + b。但为什么不以这种方式实施呢?就像在编译期间将其简单地转换为 a = a + b 而不是将其作为运算符单独实现本身不是更容易吗?这也有助于运算符重载,其中 a += b,其中 ab 是相同 class 的对象不必显式重载,只需重载 + 就够了吗?


编辑: this answer
我的问题变得更清楚了 让我用一个需要重载运算符的例子来解释我的问题:

class A {
    int ivar;
public:
    A() = default;
    A(int par_ivar) : ivar(par_ivar) { }
    A(A& a) {
        this.ivar = a.ivar;
    }
    A(A&& a) noexcept {
        this.ivar = a.ivar;
    }
    A operator+(const A& a) const {
        A temp_a;
        temp_a.ivar = this.ivar + a.ivar;
        return temp_a;
    }
    void operator=(const A& a) {
        this.ivar = a.ivar;
    }
    ~A() = default;
};

现在,让我们看一下 2 个程序的结果:
程序 1:

int main() {
    A a1(2);
    A a2(3);
    a1 = a1 + a2;  //a1.ivar = 5
    return 0;
}

prog2:

int main() {
    A a1(2);
    A a2(3);
    a1 += a2;  //compilation error!!
    return 0;
}

即使两个程序都打算做,不,做同样的事情,一个编译并运行(希望我的重载是正确的)另一个甚至不编译!!如果 += 被简单地替换为适当的 + 和 =,我们就不会觉得需要显式重载 +=。这是有意为之,还是等待添加的功能?

使用 a = a + b 将意味着使用 copy assignment(因为使用 operator =)。另一方面,a += b 默认是复合赋值。

根据cppreference,

copy assignment operator replaces the contents of the object a with a copy of the contents of b (b is not modified).

compound assignment operators replace the contents of the object a with the result of a binary operation between the previous value of a and the value of b.

使用 a = a + b,因此会导致不必要的内存使用,因为 a 在其值更改之前必须复制一次。

运算符不是由其他运算符生成的(C++20 中的 with/from <=> 除外):

提供 operator < 不允许 a > b(实际上 "logically" 等同于 b < a)。你必须实现所有(甚至通过重新使用一些)。

对于 类,a += b 不是 a = a + b

的 shorthand

但是 a.operator +=(b)operator +=(a, b)

同样,a = a + ba.operator=(operator +(a, b))(或其变体)的 shorthand

在实践中,从 operator += 实施 operator+ 比反向实施更有效。

即使用户可能根据他们的名字期望类似的行为,它们也是常规函数。

我已经看到一个矩阵迭代器,它 ++it 增加列索引而 it++ 增加行索引。

If += were simply a shorthand for a = a + <rhs of +=> overloading + operator should also implicitly overload +=, unless explicitly overloaded otherwise. But that isn't what happens. That means, a += b doesn't get converted to a = a + b.

(可能)不生成的原因可能是性能和控制:

向量(用于数学)或矩阵是很好的例子:

4 种可能的重载

Matrix operator+(Matrix&& lhs, Matrix&& rhs)      { return std::move(lhs += rhs); }
Matrix operator+(Matrix&& lhs, const Matrix& rhs) { return std::move(lhs += rhs); }
Matrix operator+(const Matrix& lhs, Matrix&& rhs) { return std::move(rhs += lhs); } // + is symmetrical :)
Matrix operator+(const Matrix& lhs, const Matrix& rhs) { auto tmp{lhs}; return tmp += rhs; }

决定的副作用允许赋予运算符不同的含义,如 "name operator":

if (42 <in> std::vector{4, 8, 15, 16, 23, 42})