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.