首页 > 解决方案 > += 运算符是如何在 C++ 中实现的?

问题描述

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

考虑这个例子,

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

现在考虑等价的表达式:

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

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


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

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 个程序的结果:
prog1:

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

编2:

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

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

标签: c++operatorsdefault

解决方案


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

提供operator <不允许a > b(这确实“逻辑上”等同于b < a)。你必须实现所有(甚至通过重用一些)。

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

但对于a.operator +=(b)operator +=(a, b)

以同样的方式a = a + ba.operator=(operator +(a, b))(或其变体)的简写

operator+在实践中,执行fromoperator +=比执行相反更有效。

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

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

If+=只是a = a + <rhs of +=>重载 + 运算符的简写,也应该隐式地overload +=,除非以其他方式显式地重载。但事实并非如此。这意味着,a += b不会转换为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; }

该决定的副作用允许给运算符赋予不同的含义,如“名称运算符”:

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

推荐阅读