[英]Why C++ lvalue objects can't be bound to rvalue references (&&)?
移動語義的想法是,您可以從另一個臨時對象(由右值引用引用)中獲取所有內容,並將“所有內容”存儲在對象中。 這有助於避免在單個構造事物足夠的情況下進行深度復制 - 因此您可以在rvalue對象中構造事物,然后將其移動到長壽命對象中。
為什么C ++不允許將左值對象綁定到右值引用? 兩者都允許我更改引用的對象,因此在訪問引用對象的內部方面對我沒有任何區別。
我能猜到的唯一原因是函數重載模糊問題。
但是為什么C ++不允許將左值對象綁定到右值引用?
假設你的意思是“為什么C ++不允許將右值引用綁定到左值對象” :它確實如此。 它不是自動的,所以你必須使用std::move
來使它顯式化。
為什么? 因為否則一個無害的函數調用會令人驚訝地破壞你沒想到的東西:
Class object(much,state,many,members,wow);
looks_safe_to_me(object);
// oh no, it destructively copied my object!
與
Class object(much,state,many,members,wow);
obviously_destructive(std::move(object));
// same result, but now the destruction is explicit and expected
關於破壞性復制的注釋:為什么我說上面的破壞性和破壞 ,我並不是說對象析構函數結束它的生命周期:只是它的內部狀態已被移動到一個新實例。 它仍然是一個有效的對象,但不再擁有以前相同的昂貴狀態。
關於術語的說明:讓我們看看我們是否可以清除上面對左值 , 右值等的不精確使用。
引用后代的cppreference :
一個左值是
具有身份且無法移動的表達式。
所以,沒有lvalue對象這樣的東西,但是有一個由左值表達式在本地命名(或引用)的對象
右邊是
一個表達式,它是一個prvalue或一個xvalue。 它可以從 。 它可能有也可能沒有身份。
prvalue (純rvalue)大致是指一個未命名的臨時對象的表達式:我們不能將我們的左值表達式轉換為這些IIUC中的一個。
xvalue (到期值)是
一個具有身份並可以移動的表達式。
其中明確包含std::move
的結果
那么實際發生了什么:
std::move
產生一個xvalue表達式(可以從中移動)引用與左值表達式相同的對象 std::move
。 本質上,需要一種機制來區分可以移動的值和不能移動的值(即需要復制)。
允許rvalues和lvalues綁定到左值引用使得這是不可能的。
因此,綁定到右值引用的值可以從(不一定總是要移動,但允許)移動,並且左值可以綁定到左值引用,並且不能從中移動。
std::move
用於允許在值類別(到rvalue)之間進行轉換以允許移動發生。
注意; const左值引用( const T&
)可以綁定到rvalues(臨時值)和左值,因為引用的對象不能更改(它被標記為const
因此無論如何都不能有任何移動)。
有一些歷史(早在C ++的早期)為什么臨時對象無法綁定到非const左值引用開始... ...細節模糊但是有一些推理修改臨時對象沒有有道理 ,因為無論如何它會在當前聲明的最后破壞。 另外,當你實際上沒有修改左值時,你可能會感覺到你正在修改左值 - 代碼的語義可能/將是錯誤的並且是錯誤的。 還有其他原因與地址,文字等相關聯。這是在移動之前,其語義固化,並且是移動及其語義的一些動機。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.