2012-05-15 76 views
4
#include <iostream> 

class Foo { }; 

Foo createFoo() { return Foo(); } 

void bar(Foo &&) { std::cout << "in bar(Foo &&)\n"; } 

void bar(Foo const &) { std::cout << "in bar(Foo const &)\n"; } 

void baz(Foo &&f) { 
    std::cout << "in baz, "; 
    bar(f); 
    // bar(std::move(f)); 
} 

int main() 
{ 
    baz(createFoo()); 
    return 0; 
} 

我的預期產出是:in baz, in bar(Foo &&),但我得到︰in baz, in bar(Foo const &)。如果我將呼叫切換到bar(請參閱評論),我會得到預期的輸出,但這對我來說似乎是錯誤的。如果沒有我將Foo&&轉換爲Foo&&,編譯器是否有某些原因不能調用bar(Foo &&)關於r值參考的困惑

在此先感謝!

+5

'Foo && f'中的'f'是一個左值,因爲它被命名,所以它不會直接綁定到右值引用。 – ildjarn

回答

13

裏面baz(Foo&& f),f是一個左值。因此,要將它作爲右值引用傳遞給bar,必須將其轉換爲右值。你可以用static_cast<Foo&&>(f)std::move(f)來做到這一點。

這是爲了避免在同一功能中多次意外地移動東西,例如在baz內多次撥打bar(f)

+3

請不要使用'static_cast'! – leftaroundabout

+0

@leftaroundabout:爲什麼不'static_cast'?很顯然'std :: move'的讀取更乾淨,並且始終可以工作,但是還有其他一些原因:'static_cast'會不好? –

+1

@Stephen Newell'static_cast'沒有清楚地表達這種意圖,可能誤導你的讀者認爲你錯誤輸入了&&爲'&&'。 –

4

簡而言之,規則是指定的右值引用是一個左值。這是爲了防止自動移出一個命名變量,然後您需要使用它。相反,未命名的臨時數據不能再次使用,因此可以自動移出。

我發現這個系列http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/是相當有幫助的,即使它有點舊。