簡體   English   中英

為什么這需要顯式的std :: move?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM