C++ Rvalue References – Understanding Rvalue References in C++11

c++c++11rvalue-reference

I think there's something I'm not quite understanding about rvalue references. Why does the following fail to compile (VS2012) with the error 'foo' : cannot convert parameter 1 from 'int' to 'int &&'?

void foo(int &&) {}
void bar(int &&x) { foo(x); };

I would have assumed that the type int && would be preserved when passed from bar into foo. Why does it get transformed into int once inside the function body?

I know the answer is to use std::forward:

void bar(int &&x) { foo(std::forward<int>(x)); }

so maybe I just don't have a clear grasp on why. (Also, why not std::move?)

Best Answer

I always remember lvalue as a value that has a name or can be addressed. Since x has a name, it is passed as an lvalue. The purpose of reference to rvalue is to allow the function to completely clobber value in any way it sees fit. If we pass x by reference as in your example, then we have no way of knowing if is safe to do this:

void foo(int &&) {}
void bar(int &&x) { 
    foo(x); 
    x.DoSomething();   // what could x be?
};

Doing foo(std::move(x)); is explicitly telling the compiler that you are done with x and no longer need it. Without that move, bad things could happen to existing code. The std::move is a safeguard.

std::forward is used for perfect forwarding in templates.

Related Question