2011-05-15 64 views
22

考慮以下功能:值返回值時是否隱式移動值參數?

Foo foo(Foo x) 
{ 
    return x; 
} 

return x調用拷貝構造函數或轉移構造函數? (讓我們離開NRVO一邊在這裏。)

探討,我寫了一個簡單Foo類,它是唯一可移動的,但不可拷貝:

struct Foo 
{ 
    Foo() = default; 
    Foo(const Foo&) = delete; 
    Foo(Foo&&) = default; 
}; 

如果值返回值參數,當移動的構造被調用,所有應該沒事。但目前的G ++編譯器抱怨return x與以下錯誤消息:

error: deleted function 'Foo::Foo(const Foo&)' 

如果我更換return xreturn std::move(x),一切都很好。由此我得出結論,如果需要,必須明確地完成從值參數的移動。 g ++的行爲是否符合?

回答

24

如果Foo有一個移動ctor,它應該被選中。

    在與類返回類型的函數返回語句
  • ,當表達式爲:

    函數參數明確地從在return語句複製省略(FDIS§12.9p31,第一子彈)排除非易失性自動對象(不是函數或catch子句參數其他)

然而的名稱,下一段落明確地帶來移動構建函數回到考慮:

當的複製操作的省音滿足準則或將一個事實,即源對象是一個函數參數,和要複製的對象被滿足節省被指定通過一個左值,重載分辨率爲副本選擇構造函數首先執行,就好像該對象由右值指定一樣。 ...

(重點在兩個引號我的。)

+9

Upvoted。這對草案來說是一個相對較晚的變化,這就解釋了爲什麼它還沒有到處實現。 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1148 – 2011-05-15 15:04:48

12

這是對的有效代碼 - G ++的行爲是不符合的。 MSVC10確實支持這種行爲。

+0

雖然我尊重你的調查,但你不能證明這裏的「有效」。 MSVC以鬆懈和允許標準禁止(例如,在類體內綁定非常量引用和專門化成員函數)的一些(方便)單號而聞名。 – 2011-05-15 16:12:27

+2

@Matthieu:我沒有說它是有效的,因爲* MSVC10支持它。這是有效的,因爲標準是這樣說的。 – Puppy 2011-05-15 16:15:40

+2

我明白了,但仍然沒有理由:) – 2011-05-15 17:56:18