0

I am confused by the rvalue type of variables in C++. The code below gives me the following compiler error

error: cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘int’ f1(b);

void f1(int&& a)
{
    std::cout << "f1 called." << std::endl;
}

int main()
{
    int a = 7;
    int&& b = std::move(a);
    f1(b);
}

moving b into f solves the problem

 f1(std::move(b));

The type of b is clearly int&&. How is b in this context considered to be an lvalue?

benno
  • 289
  • 2
  • 10
  • Take a look at this question: [Why are rvalues references variables not rvalue?](https://stackoverflow.com/questions/32620750/why-are-rvalues-references-variables-not-rvalue) – alter_igel Aug 07 '18 at 19:38
  • I see, the first thing I got wrong is that rvalue references and actual rvalues are not the same. Because rvalue references have a name, they are considered to be lvalues. But then I do not understand how std::move works, since to my understanding it simply casts the type of a variable to type&&. How is the expression f1(b) and f1(std::move(b)) different to the compiler? – benno Aug 07 '18 at 19:48
  • 1
    @benno `std::move` returns a `T&&`. Since it doesn't have a name it is not a lvalue and a rvalue reference can bind to it. That is why you were able to write `int&& b = std::move(a);`. `int& b = std::move(a);` would not compile. – NathanOliver Aug 07 '18 at 19:50
  • It is quite confusing then to speak of std::move as a casting as for example in the book ‚Effective Modern C++‘ because std::move actually returns a new variable. Thanks for the comments - I think I do understand the difference now. – benno Aug 07 '18 at 19:56
  • 1
    @benno It is a cast. `std::move` returns a reference, which isn't really a new variable. It just allows you to take a lvalue and treat it as if it were an rvalue so it can be moved from. – NathanOliver Aug 07 '18 at 20:30

0 Answers0