3

I'm new to C++ and this is my first question here so bear with me please ... I have been reading about lvalue and rvalue for a while and I think I understand most of it but there is bit that still confuses me ... so my question will be specific

rvalue references are considered lvalue (this part I understand) but functions that return rvalue references are considered rvalue (or xvalue to be specific) for instance:

int x = 32; int& Lref = x; // Lref is lvalue ... ok int& funcA(); // calling funcA() is lvalue ... ok int&& Rref = 32; // Rref is lvalue ... ok I got this int&& funcB(); // calling funcB() is rvalue ... Why? 

So the question is: why calling funcB() which return rvalue reference is considered rvalue ?

Thanks in advance.

3
  • rvalue references are considered lvalue they don't otherwise we wouldn't have 2 different types Commented Apr 11, 2016 at 19:17
  • Lref is a lvalue reference, but 32 isn't and it won't indeed compile. You'd need const& or &&, as you also show. Commented Apr 11, 2016 at 19:29
  • @ black Yes I did mistake and I just fixed it. Commented Apr 11, 2016 at 19:37

2 Answers 2

5

To answer the titular question, "rvalue reference" is a kind of type, while "xvalue" is a kind of expression.

rvalue references are considered lvalue (this part I understand)

They are not. Rvalue references are types, types are not expressions and so cannot be "considered lvalue". What you're referring to is the fact that if an expression consists solely of the name of a variable of type T&&, then it is an lvalue expression of type T.

why calling funcB() which return rvalue reference is considered rvalue

The most straightforward answer would be "by definition". A function call expression where the function's return type is T&& is an xvalue expression of type T. As for motivation, this is exactly what makes std::move do what it does: imbue any expression with the ability to be moved from (also known as "rvalue category" - see http://en.cppreference.com/w/cpp/language/value_category ).

Sign up to request clarification or add additional context in comments.

2 Comments

I admit that lvalue , rvalue and type deduction topics are very confusing... plus most websites just don't explain them in clear way ... the only way that helped me to understand them is by watching videos of Scott Meyers himself explaining them ... now I have better understanding ... and thanks for your answer
@WLION I think he makes this more complicated than it is.
1

Generally, "object" returned by a function are created on the stack part associated to the function itself. That is it, the value returned have to be copied (or moved) to a new object and this object is an rvalue.

In your code, you did a mistake for the lref. 32 is a rvalue reference.

To be simple, lvalue reference are object that we can obtain an address. We can't get the address of a rvalue reference.

int a = 50; int &b = a; // Ok because we can get the address of a int &c = 50; // Error we can't get the address of 50 int &&d = 50; // It is ok 

And it works as well with "object".

Take for example a code with an unique_ptr which is not copyable.

std::unique_ptr<int> foo() { auto ptr = std::make_unique<int>(5); return ptr; } auto a = foo(); // is correct, the ptr will be moved because it is a rvalue 

This function must return an rvalue to be correct. (Normally, the compiler when you don't specifize if it a lvalue or rvalue will use an rvalue reference).

Maybe you could take a look at : http://en.cppreference.com/w/cpp/language/value_category

If it is unclear, let me know

4 Comments

Yes I did mistake and I just fixed it but ... "We can't get the address of a rvalue reference" ... I just got the address of &Rref so that doesnt make sense.
Maybe I didn't explain well. It is not because you have declared a variable as an rvalue reference that you can't get the address from it. You can't get the address of the value "she is pointing" e.g void foo(int &&a){int *b = &a;} should work I think
What you explained above I already understand .. but my problem is only about the difference between these int&& Rref; // Rref is lvalue ..................... int&& Func() // calling Func is rvalue
@Laith The difference is identity, by definition lvalue has an identity, rvalue has not. A variable or reference declaration has an identity (Rref in your example), thus it is an lvalue. The function return does not have an identity, thus it is an rvalue (xvalue if return by rvalue reference "int&&", and prvalue if return by value "int").

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.