为什么在重载 = 运算符时通过引用 return?

Why return by reference while overloading = operator?

我知道这方面已经有很多问题了,所以请多多包涵。

所以我找到了this问题,对此我有一个修改的疑问

class Blah {
public:
    Blah();
    Blah(int x, int y);
    int x;
    int y;
    Blah operator =(Blah rhs);
};
Blah::Blah() {}
Blah::Blah(int xp, int yp) {
    x = xp;
    y = yp;
}
Blah Blah::operator =(Blah rhs) {
    x = rhs.x;
    y = rhs.y;
    return *this;
}
int main() {

    Blah b1(2, 3);
    Blah b2(4, 1);
    Blah b3(8, 9);
    Blah b4(7, 5);
    b3 = b4 = b2 = b1;
    cout << b3.x << ", " << b3.y << endl;
    cout << b4.x << ", " << b4.y << endl;
    cout << b2.x << ", " << b2.y << endl;
    cout << b1.x << ", " << b1.y << endl;
    return 0;
}

所以我没有在这里通过引用使用 return,同时重载 = 运算符,我仍然得到预期的输出。

为什么我要 return 引用?我看到的唯一区别是,在按值 returning 时调用了复制构造函数,但在按引用 returning 时没有调用复制构造函数。

有人可以为我简化一下并通过参考解释 returning 背后的 concept/idea 吗?我的 class 大约一年前就教过它,但我仍然不明白。

Why return by reference while overloading = operator?

因为:

  • 复制有时代价高昂,在这种情况下最好避免。
  • 这是约定俗成的。这也是基本类型的内置赋值运算符、classes 的编译器生成的赋值运算符以及所有标准类型的赋值运算符(据我所知)的工作方式。

鉴于您定义的特殊成员函数没有做任何特殊的事情,我建议改为遵循 class 定义:

struct Blah {
    int x;
    int y;
};

这里没有严格的对错之分。你可以用运算符重载做一些奇怪的事情,有时这是合适的。但是,很少有充分的理由 return 来自 operator= 的新实例。

return 值是启用链接。您的链接测试不完整。您的线路:

b3 = b4 = b2 = b1;

相同
b3 = (b4 = (b2 = b1));

你会看到这个案例的预期输出。但是,像这样链接

(b3 = b4) = b1;

应该先把b4赋给b3,然后把b1赋给b3。或者您可能想调用 returned 引用的方法:

(b3 = b4).foo();

当你 return 一个副本时,第二个赋值将是临时的,成员函数 foo 将在临时上调用,而不是像预期的那样在 b3 上调用。要查看实际效果,请考虑 this

的输出
int main() {

    Blah b1(2, 3);
    Blah b2(4, 1);
    Blah b3(8, 9);
    Blah b4(7, 5);        
    (b3 = b4) = b1;
    cout << b3.x << ", " << b3.y << endl;
    cout << b1.x << ", " << b1.y << endl;
    return 0;
}

当 return复制时:

7, 5
2, 3

当 return引用时:

2, 3
2, 3

更简单的原因是你不想return在不需要复制的时候复制。