Biagio Festa Biagio Festa - 2 months ago 4
C++ Question

r-value parameters in a function

I was wondering about a c++ behaviour when an r-value is passed among functions.

Look at this simple code:

#include <string>

void foo(std::string&& str) {
// Accept a rvalue of str

void bar(std::string&& str) {
// foo(str); // Does not compile. Compiler says cannot bind lvalue into rvalue.
foo(std::move(str)); // It feels like a re-casting into a r-value?

int main(int argc, char *argv[]) {
return 0;

I know when I'm inside
function I need to use
function in order to invoke
function. My question now is why?

When I'm inside the
function the variable
should already be an r-value, but the compiler acts like it is a l-value.

Can somebody quote some reference to the standard about this behaviour?


str is a rvalue reference, i.e. it is a reference only to rvalues. But it is still a reference, which is a lvalue. You can use str as a variable, which also implies that it is an lvalue, not a temporary rvalue.

An lvalue is, according to §

An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. [ Example: If E is an expression of pointer type, then *E is an lvalue expression referring to the object or function to which E points. As another example, the result of calling a function whose return type is an lvalue reference is an lvalue. —end example ]

And an rvalue is, according to §

An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.

Based on this, str is not a temporary object, and it is associated with an object (with the object called str), and so it is not an rvalue.

The example for the lvalue uses a pointer, but it is the same thing for references, and naturally for rvalue references (which are only a special type of references).

So, in your example, str is an lvalue, so you have to std::move it to call foo (which only accepts rvalues, not lvalues).