揭開std::move 轉換魔法的神秘面紗
當調用std::move() 時,令人費解的是觀察到引用的右值參數可以綁定到左值,通常限制左值附加到右值引用。深入研究 std::move() 的實現揭示了這個明顯悖論的關鍵。
剖析std::move() 實作
從精煉的開始std::move() 的版本:
template <typename T> typename remove_reference<T>::type&& move(T&& arg) { return static_cast<typename remove_reference<T>::type&&>(arg); }
情況1:使用右值呼叫move()
當move() 與右值一起使用時,例如臨時物件:
Object a = std::move(Object()); // Object() is temporary, hence prvalue
產生的模板實例化為:
remove_reference<Object>::type&& move(Object&& arg) { return static_cast<remove_reference<Object>::type&&>(arg); }
由於remove_reference將T&轉換為T或T&&轉換為T,且Object是一個普通值,所以最終的函數形態變成:
Object&& move(Object&& arg) { return static_cast<Object&&>(arg); }
強制轉換至關重要,因為命名的右值引用被視為左值。
情況2:使用左值呼叫move()
使用左值呼叫move() 時:
Object a; // a is an lvalue Object b = std::move(a);
產生的move () 實例化為:
remove_reference<Object&>::type&& move(Object& && arg) { return static_cast<remove_reference<Object&>::type&&>(arg); }
再次,remove_reference 將Object& 轉換為Object,產生:
Object&& move(Object& && arg) { return static_cast<Object&&>(arg); }
引用折疊的本質
理解Object& && 及其綁定左值的能力是解開謎團的關鍵。 C 11 引入了引用折疊的特殊規則,其中規定:
Object & && = Object & Object & &&& = Object & Object && & = Object & Object && &&& = Object &&
因此,Object& && 實際上轉換為 Object&,一個可以輕鬆綁定到左值的典型左值引用。
結果函數
使用這些規則,最終函數將變為:
Object&& move(Object& arg) { return static_cast<Object&&>(arg); }
鏡像右值的實例化,它將其參數轉換為右值引用,從而確保統一的行為.
remove_reference 的重要性
當檢查替代函數時,remove_reference 的目的變得顯而易見:
當檢查替代函數時,remove_reference 的目的變得顯而易見:template <typename T> T&& wanna_be_move(T&& arg) { return static_cast<T&&>(arg); }當用左值實例化時:
Object& && wanna_be_move(Object& && arg) { return static_cast<Object& &&&>(arg); }應用引用折疊規則揭示了一個不可用的類似移動的函數,為左值參數返回左值。罪魁禍首是缺少remove_reference,它阻礙了正確轉換為右值引用。
以上是當右邊值參考應該只綁定到右邊值時,std::move() 如何綁定到左值?的詳細內容。更多資訊請關注PHP中文網其他相關文章!