c++ - 为什么我们在重载 << 运算符而不是重载 = 和 + 运算符时通过引用返回对象?
问题描述
我试图查阅这本书,我发现那里的原因是重载 << 运算符的运算符函数的原型是:
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;
这个函数也有一个参考参数。但是我们按值传递对象作为实际参数(在重载 << 运算符时,我们通过引用返回,因为我们必须将它传递给不能按值对象返回的引用参数,所以我们为什么不在这里做同样的事情,即通过引用返回)。
解决方案
如评论中所述,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
。
推荐阅读
- c# - C#/PHP 如何构建不能被滥用的 API
- python - Mathematica 的 NDSolve 和 SciPy 的 solve_ivp 返回不同的结果
- html - 网格中的多个按钮
- node.js - Node.js strApi 连接到谷歌云
- c++ - 如何创建一个行为几乎与 int64_t 完全相同的类型安全句柄,但不允许句柄类型之间的隐式转换?
- webrtc - webRTC 直播 Nativescript
- python - 如何使用请求“单击”按钮
- c++ - 为什么修改另一个变量引用的字段会导致意外行为?
- reactjs - HoC 组件连接到 redux arround 组件连接到 redux
- java - 通过保留物理尺寸降低图像 PPI(每英寸像素数)