作者adxis (Acquire higher)
看板C_and_CPP
標題[分享]std::forward, rvalue ref, and algorithm
時間Mon Jul 16 16:15:39 2012
有用過 <algorithm> 的人或許會發現,傳給該演算法的 compare functor 或是
predicator 都是 pass-by-value,這對於想要在 functor 裡面偷動手腳存東西的
人來說是個問題,舉個例子:
template<typename T>
struct my_compare{...};
void func()
{
my_compare<int> cmp;
std::vecotr<int> v{3,2,1,6,9}; // 偷用一下 C++11
std::sort(v.begin(), v.end(), cmp);
}
注意 std::sort 是遞迴地執行運算, 因此 cmp 這個 functor 會被不斷地複製
以 sort n 個數值來講,平均複製的次數是 O(nlogn),另外由於 sort 設計的關係
他不會回傳 functor ,以致於沒辦法在 cmp 內部保留狀態。
在 C++11 以前的解法一個是自己改寫 sort ,確保 functor 是 pass by reference
(明確指定樣板參數型別),另一個就是用 boost::bind 去把 functor 重新打包
std::sort(v.begin(), v.end(),
boost::bind(
&my_compare<int>::operator(),
&cmp,
_1, _2)
);
這樣複製就是發生在打包出來的 unspecified function 而不是 cmp 本身;
註:感謝 Chikei 提醒,TR1 裡面就有 reference_wrapper。可以簡單的
sort(..., ..., ref(cmp); 達成本文目的。
雖然目的已經達成,可是我還沒用到 std::foward<T> =.= ...
所以用了他有甚麼效果,主要就是 rvalue reference 的解析。
在 C++11 之後,利用 std::forward 可以保證飾詞(const) 與
reference 語意不會丟失,因此,他能正確解析出 rvalue reference
並呼叫 move constructor,(這個時候當然狀態就拿不回來啦):
http://yangacer.twbbs.org/~yangacer/samples/forward.html
只是 GCC4.7 裡的 <algorithm> 沒有改成如此。另外,在 functor 裡面保
存狀態到底是不是個好主意,我也不太確定。
------
寫完才想到 Lambda function ...。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.123.17.77
推 damody:推好仔細 "gcc4.7沒改" 不過我還在 mingw 4.6.2 07/16 16:25
→ legnaleurc:compare 用的 function 有 state 的確不是個好主意 07/16 17:13
→ legnaleurc:因為呼叫次序次數都不確定 07/16 17:14
→ adxis:可能 unary functor 比較常用吧 e.g. for_each 07/16 18:27
推 zaqimon:我真的不懂C++啊 我還是用C就好了 07/17 13:37
推 shaopin:你這code是打算怎麼用儲存好的狀態? 假設可以的話... 07/17 13:52
link 裡的 code 嗎? 就只是記錄哪些值被比較而已。
→ Chikei:pre-C++11有tr1::reference_wrapper可以用 07/17 14:21
已修正
推 shaopin:除了sort以外 其他的algorithm還有也是這樣的嗎? 07/17 14:39
拿不到運算後 functor 的嗎? 沒有 return functor 的。
※ 編輯: adxis 來自: 220.132.19.9 (07/17 14:53)
※ 編輯: adxis 來自: 220.132.19.9 (07/17 14:55)
※ 編輯: adxis 來自: 220.132.19.9 (07/17 15:04)