作者Feis (坐吃山空)
看板C_and_CPP
标题Re: [问题] 运算子多载一问
时间Sun Jun 17 21:44:39 2018
※ 引述《d630200x (DOGE)》之铭言:
: 在一般运算子多载中的宣告为下
: 传回型别 operator运算子符号(.....)
: 然而看到比如要多载++前置或者是右移运算子>>时
: 宣告会变成
: 传回型别& operator运算子符号(.....)
: 个人不太能理解这个&的意义,翻来翻去也没有找到解答
首先先确定知道回传的资料型别为 T& 时,& 表示其回传的是 reference (参考)
因此其回传的应为其中一个运算元的本尊,而非暂时物件,不然就会无中生有
下去的问题就变成什麽时候要传本尊,什麽时候要产生暂时物件
这个跟我们期望这个运算子怎麽作用有关
以 a + b 的结果来说,回传 a 本尊或 b 本尊都极其不合理.
因为这不只意味着 a + b 计算完之後其结果会存在 a 或 b 上,
也意味着 a + b = 3 这写法是合法的 (你可以试着写写看)
你应该不会期望做完 a + b = 3 之後,是 a 或 b 其中一个会变成 3 吧
可以想成如果每次都回传一个暂时物件表示计算结果是最简单的,T& 反而麻烦
但是这样会遇到一些困难:
1. 语意问题
int a = 3;
int b = 0;
int &c = b = a;
如果我们要让这语法合法的话,b = a 的计算结果,也就是 operator= 必须回传 b 本尊
这造就了基本上所有赋值运算都必须要回传 T&
相对的,因为 ++b 也是种赋值运算
int &c = ++b;
要合法的前提也是 operator++ (pre-) 需要回传 T&
operator++ (post-) 反而是例外,因为其回传值与本尊的值就不一样
int &c = b++; // 这边的 c 参考的会是 +1 之前的 b,要嘛语意不合理,要嘛无中生有
2. 连锁呼叫时的复制问题
当你有一种类别物件支援某种可以连锁呼叫的运算子时,可能会在复制的时候发生问题
例如 cout << a << b << c << d << e;
在语意上是希望达到
cout << a; cout << b; cout << c; cout << d; cout << e;
的效果
这就必须让 operator<< 的回传值与其中一个运算元 (cout) 相同
於是我们一方面可能需要回传时每次都复制一次 cout 造成效率问题,
另一方面也许 cout 根本就因为运作特性不能复制.
或者你根本期望他套用在同一个物件上
因此选择回传其中一个运算元 (cout) 的本尊 (reference, T&) 是最适当的方式
就结论来说,C++ 并没有严格要求你是不是要回传 reference
运算子多载重要的是让使用者直觉的操作,不要做出不预期的运算
在考量使用者可能的使用情境後,选择最适当的设计
--
以上都是我的猜想,如果哪里有什麽问题再麻烦回覆讨论一下~
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 140.122.83.198
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1529243086.A.226.html
※ 编辑: Feis (140.122.83.198), 06/17/2018 22:11:35
1F:推 sarafciel: 推一个 清楚明了 06/17 22:17
2F:推 dannypsnl: 推,很清晰的说明 06/17 23:38
4F:→ handsome616: 为什麽24行可以直接给值,是怎麽运作的… 06/20 00:01
5F:→ handsome616: 有人可以解惑吗,谢谢 06/20 00:02
6F:推 jerryh001: *ptr是int 所以可以给 ptr是指标 不能直接给 06/20 00:35
7F:→ handsome616: 可是第18行不是只回传一个数值回来吗 06/20 10:59
8F:→ sarafciel: int operator *() { return *ptr; }<=这才是回传数值 06/20 11:16
9F:→ sarafciel: int & operator *() {...}<=这是传reference 06/20 11:17
10F:→ sarafciel: 而reference这东西实际上是const pointer 06/20 11:19
11F:→ sarafciel: 你单看大括号内的return *ptr可能有误解 06/20 11:19
12F:→ sarafciel: 实际上往外传的时候对*ptr又做了一次取址 06/20 11:20
13F:→ sarafciel: 只是这些部分被reference的operator藏起来了而已 06/20 11:21
14F:推 handsome616: 太感谢你!! 06/20 12:54