Re: [問題] 運算子多載一問

看板C_and_CPP作者 (坐吃山空)時間5年前 (2018/06/17 21:44), 5年前編輯推噓5(509)
留言14則, 4人參與, 5年前最新討論串2/2 (看更多)
※ 引述《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

06/17 22:17, 5年前 , 1F
推一個 清楚明瞭
06/17 22:17, 1F

06/17 23:38, 5年前 , 2F
推,很清晰的說明
06/17 23:38, 2F

06/20 00:00, 5年前 , 3F

06/20 00:01, 5年前 , 4F
為什麼24行可以直接給值,是怎麼運作的…
06/20 00:01, 4F

06/20 00:02, 5年前 , 5F
有人可以解惑嗎,謝謝
06/20 00:02, 5F

06/20 00:35, 5年前 , 6F
*ptr是int 所以可以給 ptr是指標 不能直接給
06/20 00:35, 6F

06/20 10:59, 5年前 , 7F
可是第18行不是只回傳一個數值回來嗎
06/20 10:59, 7F

06/20 11:16, 5年前 , 8F
int operator *() { return *ptr; }<=這才是回傳數值
06/20 11:16, 8F

06/20 11:17, 5年前 , 9F
int & operator *() {...}<=這是傳reference
06/20 11:17, 9F

06/20 11:19, 5年前 , 10F
而reference這東西實際上是const pointer
06/20 11:19, 10F

06/20 11:19, 5年前 , 11F
你單看大括號內的return *ptr可能有誤解
06/20 11:19, 11F

06/20 11:20, 5年前 , 12F
實際上往外傳的時候對*ptr又做了一次取址
06/20 11:20, 12F

06/20 11:21, 5年前 , 13F
只是這些部分被reference的operator藏起來了而已
06/20 11:21, 13F

06/20 12:54, 5年前 , 14F
太感謝你!!
06/20 12:54, 14F
文章代碼(AID): #1R9cNE8c (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1R9cNE8c (C_and_CPP)