首页 > 解决方案 > 为什么我们在重载 << 运算符而不是重载 = 和 + 运算符时通过引用返回对象?

问题描述

我试图查阅这本书,我发现那里的原因是重载 << 运算符的运算符函数的原型是:

friend ostream& operator<<(ostream&, const className&);

现在考虑以下语句:

cout << myRectangle << yourRectangle;

该语句等价于以下语句:

operator<<(operator<<(cout, myRectangle), yourRectangle); //Line A

因为运算符 << 的结合性是从左到右的。要执行前面的语句,必须首先执行表达式:

cout << myRectangle

也就是说,表达式:

operator<<(cout, myRectangle)

执行这个表达式后,输出 myRectangle 的值,函数 operator << 返回的任何内容都将成为 operator << 的左侧参数(即函数 operator<< 的第一个参数),以便输出对象 yourRectangle 的值(参见 A 行中的语句)。运算符 << 的左侧参数必须是 ostream 类型的对象,因此表达式: cout << myRectangle 必须将对象 cout(不是它的值)返回到第二个运算符 << 的左侧,以便输出 yourRectangle 的值。因此,函数 operator<< 的返回类型必须是对 ostream 类型对象的引用。

这意味着您不能将对象按值作为参数传递,而形式参数通过引用获取它。所以对我来说为什么在重载 << 运算符时我们通过引用返回是有道理的。但我感到困惑的是在这个声明中:

tempRectangle = myRectangle + yourRectangle + anyRectangle;

根据运算符的优先级和结合性,编译器会首先执行:

myRectangle + yourRectangle

这相当于:

myRectangle.operator+ (yourRectangle); // Line B

► 这是我的第一个困惑,在执行 B 行后,它将按值返回对象(然后由第三个对象添加,即 anyRectangle)。那么如何根据 B 行编写这个加法(因为我们没有任何名称返回的那个对象,所以它是如何执行这个加法的)。

► 第二个困惑是,在此语句中添加了所有三个对象之后:

tempRectangle = myRectangle + yourRectangle + anyRectangle;

我们有一个按值返回的对象,然后将其传递给 operator= 函数以分配它 tempRectangle。现在这与 << 运算符发生的情况相同。由于 operator= 函数的原型是:

className operator+(const className&) const;

这个函数也有一个参考参数。但是我们按值传递对象作为实际参数(在重载 << 运算符时,我们通过引用返回,因为我们必须将它传递给不能按值对象返回的引用参数,所以我们为什么不在这里做同样的事情,即通过引用返回)。

标签: c++oopoperator-overloadingreturn-type

解决方案


如评论中所述,operator=应返回参考。另一方面operator+是不同的,因为在

auto c = a + b;

通常,operator+两个操作数都保持不变,结果会创建一个新对象。例如

struct foo {
    int value;
    foo operator+(const foo& other) const {
        foo result;
        result.value = value + other.value;
        return result;
    }
};

如果你operator+像这样链接

auto c = (a + b) + c;

Thenoperator+(c)既不调用a也不调用,b而是调用 的结果a+b


推荐阅读