[爆卦]operator運算元是什麼?優點缺點精華區懶人包

為什麼這篇operator運算元鄉民發文收入到精華區:因為在operator運算元這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者Feis (坐吃山空)看板C_and_CPP標題Re: [問題] 運算子多載一問時間Sun Ju...


※ 引述《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://www.ptt.cc/bbs/C_and_CPP/M.1529243086.A.226.html
※ 編輯: Feis (140.122.83.198), 06/17/2018 22:11:35
sarafciel: 推一個 清楚明瞭 06/17 22:17
dannypsnl: 推,很清晰的說明 06/17 23:38
handsome616: https://ideone.com/Ipymxh 06/20 00:00
handsome616: 為什麼24行可以直接給值,是怎麼運作的… 06/20 00:01
handsome616: 有人可以解惑嗎,謝謝 06/20 00:02
jerryh001: *ptr是int 所以可以給 ptr是指標 不能直接給 06/20 00:35
handsome616: 可是第18行不是只回傳一個數值回來嗎 06/20 10:59
sarafciel: int operator *() { return *ptr; }<=這才是回傳數值 06/20 11:16
sarafciel: int & operator *() {...}<=這是傳reference 06/20 11:17
sarafciel: 而reference這東西實際上是const pointer 06/20 11:19
sarafciel: 你單看大括號內的return *ptr可能有誤解 06/20 11:19
sarafciel: 實際上往外傳的時候對*ptr又做了一次取址 06/20 11:20
sarafciel: 只是這些部分被reference的operator藏起來了而已 06/20 11:21
handsome616: 太感謝你!! 06/20 12:54

你可能也想看看

搜尋相關網站