看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《hpps (hpps)》之銘言: : 我想問的是,如果我寫 : s3 = s1 + s2; : 用的是Rvalue reference的版本,那這樣s1不是會被修改到嗎? 不會,這個用的是 LRef 的版本,以下詳述。 : 如果我不想要s1不被修改( 可能之後會用 ),又不想失去效率, : 那該如何寫比較好?? 試考慮這兩個 overloading // [1] LRef + LRef string operator+(const string& a, const string& b) { return a + b; } // [2] RRef + LRef string operator+(string&&a, const string& b) { return a +=b ; } (兩個版本的第二個參數都是 LRef,我們不鳥他,只專注在第一個參數) 注意,這兩個版本,是兩個同時都存在,不是只有一個,所以叫做 overloading。 考慮下面這個運算式 string s1; string s2; string s3; string s4 = s1 + s2 + s3; 注意 s4 這行,他實際上會被分成兩步來作 1. 計算 s1 + s2,結果是 (tmp) 2. 計算 (tmp) + s3 現在因為你有兩個版本的 operator+, 所以會呼叫到哪一個,其實需要經過多載決議(overloading resolution)才知道。 先講答案,第一步 s1 + s2 呼叫的是 [1] LRef + LRef 的版本, 第二步 (tmp) + s3 呼叫的是 [2] RRef + LRef 的版本。 差別在於 s1 是個 lvalue,而 (tmp) 是個 non-const rvalue, non-const rvalue 的特色就是 「他等一下就要煙消雲散了,等一下你就沒有機會碰到他了」 而且!他其實不在意你修改他,因為他是 non-const。 既然他不介意你修改他,而且他馬上就要煙消雲散了, 也就是說「即使你現在亂改,也不會有人發現」 而所謂亂改,表示你可以直接把他裡面的資源,甚至他本身,都整個拿來重新使用。 (反正他等一下就要蒸發了,你不幹白不幹) 所以你在實作 RRef + LRef 這個版本的時候, 就可以放心的使用 a,因為他不可能再被別人使用。 只有在運算式計算值的這個過程的這個當下的唯一這個時間點,你有機會碰到他。 因為 rvalue 就是暫時變數,暫時變數就沒有名字,你不可能再遇到他了。 你說「我之後可能還會用到 s1」 但不用擔心,因為 s1 + s2 會呼叫的是 LRef + LRef 的版本, 你注意這個版本,兩個參數都被 const 修飾, 所以你的實作的既不能、也無法去修改 s1。 也就是說,透過 overloading 兩個版本: 1. const lvalue 2. non-const rvalue 你就可以兼顧安全跟效率 -- To iterate is human, to recurse, divine. 遞迴只應天上有, 凡人該當用迴圈.   L. Peter Deutsch -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 58.115.141.224
hpps:懂了,因為我剛剛沒overloading兩個版本,只是兩個分開測試 03/24 23:47
lunastorm:長知識~ 03/25 00:27
loveme00835:有神快拜 m(_ _)m 03/25 02:33
yoco315:...... 03/25 02:38
hilorrk:一樓....XD 03/25 07:21
whitglint:淺顯易懂!推! 03/26 08:56
VictorTom:推:) 03/27 01:12