當我閱讀一些文章時,右值引用和移動語義通常一起描述。然而,據我所知,右值引用只是引用右值,並且與移動語義無關。移動語義可能會被實現,甚至可能甚至不使用右值引用。所以問題是,爲什麼要移動構造函數/運算符=使用右值引用?只是爲了更容易編寫代碼?爲什麼右值引用與移動語義相關聯?
回答
考慮這個問題。我們要支持兩種基本的移動操作:移動「構造」並移動「分配」。我在那裏使用了引號,因爲我們不一定要用構造函數或移動賦值操作符來實現它們;我們可以使用別的東西。
移動「構造」意味着通過從現有對象中傳輸內容來創建新對象,從而刪除舊對象不會釋放現在在新對象中使用的資源。移動「賦值」意味着採用預先存在的對象並從現有對象中傳輸內容,以便刪除舊對象不會釋放現在在新對象中使用的資源。
好的,所以這些是我們想要做的操作。那麼,該怎麼做呢?
移動「建築」。雖然我們沒有有來執行這個帶有構造函數調用,但我們真的想要。我們不想強迫人們進行兩階段移動建設,即使它是在一些神奇的功能調用之後。所以我們希望能夠實現運動作爲構造函數。好的。
問題1:構造函數沒有名字。因此,您只能根據參數類型和重載解析來區分它們。我們知道T
類型的對象的移動構造函數必須將T
類型的對象作爲參數。因爲它只需要一個參數,所以它看起來完全像一個拷貝構造函數。好的,現在我們需要一些方法來滿足超載。我們可以引入一些標準庫類型,一個std::move_ref
。這將像std::reference_wrapper
,但它將是一個獨特的類型。因此,你可以說移動構造函數是一個構造函數,它需要一個std::move_ref<T>
。好,很好:問題解決了。
只有不;我們現在有新的問題。考慮下面的代碼:
std::string MakeAString() { return std::string("foo"); }
std::string data = MakeAString();
忽略省音,C++ 11的表情值類別規則指出這是從一個函數由返回值類型是一個prvalue。因此,它會自動被移動構造函數/賦值運算符使用。不需要std::move
等。
要做到這一點的方法就是需要這樣的:
std::string MakeAString() { return std::move(std::string("foo")); }
std::string data = std::move(MakeAString());
那些std::move
電話將需要避免複製的兩個。您必須移出臨時值並返回返回值,然後移出返回值並返回data
(再次忽略elision)。
如果您認爲這只是一個小小的煩惱,請考慮還有哪些右值引用了我們:完美轉發。如果沒有特殊的引用合攏規則,就無法編寫正確的轉發功能,它可以完美地轉發副本並移動語義。 std::move_ref
將是一個真正的C++類型;你不能像使用右值引用一樣將任意規則像參考摺疊一樣放在它上面。
在一天結束時,您需要某種形式的語言結構,而不僅僅是一種庫類型。通過使它成爲一種新的參考,您可以定義新的規則,以便綁定到該參考(以及不可以)的內容。而且您可以定義特殊的引用合攏規則,使完美的轉發成爲可能。
連接的是,它是安全的從右值(因爲(在不存在鑄件)右值指的是在其壽命的末尾的對象),所以一個構造函數的移動右值引用可以通過從引用對象中盜取/移動而安全地實現。
從C++ - 的視圖語言點,這是在連接的端部,但在標準庫進一步通過不斷從左值拷貝和建設從右值舉動使施工此連接上膨脹,並通過提供幫助函數(例如std::move
),它使得直接選擇是移動還是複製特定對象(通過改變表達式中導致複製/移動的對象的值類別)。
移動語義可以在沒有右值-參考的情況下實現,但它會少得多整齊。許多問題需要解決:
如何通過非const引用捕捉右值?
如何區分副本的構造函數和移動的構造函數?
如何確保移動被用在任何他們將會進行安全優化的地方?
如何編寫可移動和可複製對象的通用代碼?
- 1. 爲什麼右關聯不與聲明語句
- 2. 移動語義和右值引用提高了性能
- 3. 爲左值移動語義
- 4. 移動語義和引用語義
- 5. 爲什麼UIView右移offsetBy
- 6. 右值引用未定義的行爲
- 7. 將右值引用定義爲空
- 8. 爲什麼在動態mem分配中移動語義與淺拷貝具有相同的行爲?
- 9. 爲什麼`UnsupportedOperationException`拋出嘗試將SurfaceView與相機關聯?
- 10. 這是什麼,以及什麼vimscript函數與它相關聯?
- 11. 爲什麼這個右值引用綁定到一個左值?
- 12. 移動語義和常量引用
- 13. 爲什麼std :: tuple會分解爲右值引用
- 14. 爲什麼ActiveRecord只能自動提供相互關聯?
- 15. 動態數據關聯相關表值?
- 16. 散景與自定義索引相關聯刷牙
- 17. 將右值引用參數轉換爲右值引用?
- 18. std :: move into static_pointer_cast:爲什麼static_pointer_cast沒有右值引用超載?
- 19. 爲什麼「decltype(i + j)」的結果不是右值引用?
- 20. 爲什麼指針的這個引用是右值?
- 21. 將聯繫人與用戶相關聯
- 22. 爲給定單詞輸入與語義相關的關鍵字
- 23. 爲什麼在右值的情況下轉發引用不會導致右值引用?
- 24. 什麼是關聯數組索引移動到不同的位置
- 25. Rails測試:爲什麼關聯引用出錯
- 26. 爲什麼對ActiveRecord關聯的引用失敗?
- 27. 爲什麼添加對右值引用的引用不是錯誤?
- 28. 爲什麼ActiveRecord的關聯回報每一個相關聯的對象
- 29. 什麼java類與這些nutch命令相關聯?
- 30. C++用ostringstream移動語義