lvalue and rvalue

I'm starting to take a look at the C++ 11 feature lvalue and rvalue differences and move sematics.

I understand that an rvalue is a value that does not have a name and/or cannot be taken address of. However when can something not be taken address of in the context of method calls.

Book GetBook()
{
return Book("Author", "Title"); // Cannot be taken address of, rvalue?
}

However we use GetBook and capture the returnvalue.

Book b1 = GetBook(); // lvalue
Book& b2 = GetBook(); // lvalue
Book&& b3 = GetBook(); // rvalue

So the rules that rvalues cannot be taked address of is wrong? Here i captured by reference b2, same way b3 rvalue did.

My question is how exactly does rvalues behave differently then lvalues, ref this example?
rvalue does have an address, but it is prohibited to take it, or create a modifiable reference to it, because it is a temporary and will be destroyed right away, making adress point to invalid object and leave reference dangling. So it makes no sense to do so. Also it can help with optimisation, as number of potential observers decreases and optimizer can do more here.

r-value references and const references are stated to prolong lifetime of temporaries, so you can make such a reference to them.

Line containing b2 is illegal. However const Book& b2 = GetBook(); would compile as const references are prolonging lifetime of temporary return value.

Edit: http://en.cppreference.com/w/cpp/language/value_category
Last edited on
If

Book& b2 = GetBook(); // lvalue

compiles for you then you're probably using the Visual C++ compiler.

Upping the warning level to /W4 results in the following warning for this line:

warning C4239: nonstandard extension used : 'initializing' : conversion from 'Book' to 'Book &'
1>        A non-const reference may only be bound to an lvalue


Andy

PS If you are using the Visual C++ compiler to learn how to write standard C++ it is prob best you (a) up the warning level to at least /W4 (and maybe even /Wall), and (b) disable language extensions (in project's proprerties, find "Configuration Properties" > "C/C++" > "Language" and alter "Disable Language Extensions" to "Yes (/Za)") This will make the above warning an error, as correct for standard C++.

BUT if you are writing code with uses WinAPI calls you cannot disable the language extensions, and /W4 is as high as you should go (<windows.h> causes a lot of warnings at /Wall.)
Last edited on
Line b2 is working in Visual C++ 2013 Update 4.

So what happens with line b3? How does the rvalue reference hold on to the object if it cannot take the address? Copied (shallow)?
As I said, it prolongs its lifetime. Temporary object just is not destroyed until reference to it does.
So could we say that rvalue references has as a primary reason for beeing the ability to increase lifetime of temporary objects?

If so what about this:

Book b1();

Book&& b2 = std:move(b1); // why do we need this?

Why would we need this last statement if we could just get a regular reference to the object instead?
Main reason for rvalue references is to enable move semantics. Prolonging lifetime is nessesary so we can actualy do stuff with objects (usually ripping out their internals) before they are destroyed.

Prolonging lifetime for const references is done exactly for that to: to enable reference semantics for temporaries. So you would not need to pay for creation of object twice if something prevents RVO.
iKjetil wrote:
So the rules that rvalues cannot be taked address of is wrong?

Nothing in your code attempts to take the address of an expression.

This is an rvalue expression: GetBook(). It is an rvalue because it is a function call expression where the function return type is not a reference type.

This is an attempt to take its address: Book* p = &GetBook();. It will not compile because address-of operator requires an lvalue on the right.
Topic archived. No new replies allowed.