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.
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.
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.)
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.
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.