2017-10-17 82 views
3

下面是示例代碼:傳遞的unique_ptr右值引用結果編譯錯誤

using namespace std; 
struct A { 
    A(unique_ptr<int> s) 
    : _s(move(s)){} 

    unique_ptr<int> _s; 
}; 

int main(int argc, const char * argv[]) { 

    auto&& ptr = make_unique<int>(5); 
    A a{ptr}; // Error 
    A b{move(ptr)}; // OK 
    return 0; 
} 

我的第一個猜測是,應該不使用「移動」的工作,但我得到「呼叫隱式刪除,拷貝構造函數」的鏗鏘。也許'ptr'的類型不是右值(奇怪?)?有人能澄清一下嗎?

+0

的可能的複製[我如何通過一個獨特的\ _ptr參數構造函數或一個函數?](https://stackoverflow.com/questions/8114276/how-do-i-pass-a-unique-ptr-argument-to-a-constructor-or-a-function) – acraig5075

回答

4

這裏有幾件事情,其中​​大部分涉及價值類別分類中各個部分標準的表述。但是它的要點如下:

ptr的類型的扣除將遵循轉發參考的規則。所以是的,這將是unique_ptr<int>&&。但ptr不是一個右值。這是理解棘手的事情。這是一個你肯定會右值的引用,但是現在該對象不再是未命名的,對它的引用也不是。

它現在是一個名稱的對象。直覺上,因爲你可以指定它,它是一個左值(一般意義上)。因此,它本身不會綁定到右值引用。所以你最終試圖調用複製構造函數。

要移動它,您需要再次將其轉換爲即將到期的值(從類型系統的角度來看)。這就是std::move通過返回一個(未命名的)右值引用。

1

無論是傳遞一個r值:

A a{ make_unique<int>(5) }; 

或std ::移動的左值

auto ptr = make_unique<int>(5); 
A b{ move(ptr) };