作者yoco315 (眠月)
看板C_and_CPP
標題Re: [問題] 關於C++的Rvalue reference
時間Sun Mar 24 23:24:41 2013
※ 引述《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