2012-05-15 38 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/是相当有帮助的,即使它有点旧。