[英]Why does this need an explicit std::move?
假設我有一個Foo
類,其中包含從另一個類Bar
std::unique_ptr
對象構造的std::vector
。
typedef std::unique_ptr<Bar> UniqueBar;
class Foo {
std::vector<UniqueBar> bars;
public:
void AddBar(UniqueBar&& bar);
};
void Foo::AddBar(UniqueBar&& bar) {
bars.push_back(bar);
}
這會導致編譯錯誤(在g ++ 4.8.1中),表明已刪除std::unique_ptr
的副本構造函數,這是合理的。 這里的問題是,由於bar參數已經是一個右值引用,為什么調用std::unique_ptr
的副本構造函數而不是其move構造函數?
如果我在Foo::AddBar
顯式調用std::move
,那么編譯問題就消失了,但是我不明白為什么需要這樣做。 我認為這是多余的。
那么,我想念什么?
基本上,每個具有名稱的對象都是一個左值。 當您使用右值引用將對象傳遞給函數時,該函數實際上會看到一個左值:它已被命名。 但是,右值引用的作用是表明它來自已准備好傳輸的對象。
換句話說,右值引用是不對稱的:
std::move(o)
) 似乎令人困惑,一個右值引用綁定到一個右值 ,但用作表達式的是一個左值 。
bar
實際上是一個左值,因此您需要將其傳遞給std::move
,以便在對push_back
的調用中將其視為右值。
Foo::AddBar(UniqueBar&& bar)
重載只是確保在對Foo::AddBar
的調用中傳遞了右值時選擇了此重載。 但是bar
參數本身具有名稱,並且是左值。
bar
被定義為右值引用,但其值類別為左值。 之所以如此,是因為對象具有名稱。 如果有名稱,則為左值。 因此,顯式的std::move
是必需的,因為其目的是擺脫名稱並返回xvalue(eXpiring-rvalue)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.