l-value/r-value references and storage

I understand that compilers can optimize references out of existence so that they don't "occupy storage" (http://en.cppreference.com/w/cpp/language/reference ). For example, this is why the outputs below show identical addresses.

1
2
3
4
5
6
7
//In other words, the 'y' variable below, despite possibly being a lvalue, 
//does not cause the compiler to allocate space to store its value 
//(i.e., the reference here is not implemented as a pointer of sorts)
int x;
int &y = x;
std::cout << &x << endl;
std::cout << &y << endl;


1) Could someone confirm that this never happens to rvalue references (i.e., rvalue references such as the 'z' variable below will always occupy storage)?

 
int&& z = 5;

-----------------------------------------------------------------------------

In addition:

I think I've seen C++11/14 tutorials state that b/c we can take the address of a rvalue reference variable, such variables are themselves lvalues.

2) Can the same be said of lvalue references? For example, the lvalue reference variable 'y' above is itself a lvalue, even though it does not occupy storage.

This appears to be true b/c any qualifying expressions can be a lvalue (http://en.cppreference.com/w/cpp/language/value_category ); such expressions do not necessarily need to be objects nor occupy storage (for example, even a string literal can be a lvalue, even though I've never seen it used on the left side of the = operator).

Thanks
Last edited on
References are not objects. Better see them as alternative names for objects.

There is no valid way of getting the address of a reference. All operators that you apply to a reference will always work the same as if you used them directly on the object that the reference is referring to.

Compilers are free to optimize the code as long as the defined behaviour is not changed, so it is possible for any variable (including all types of references) to be optimized away completely. The only way I know you can check if something really occupies storage is to study the resulting assembly code.
Last edited on
Thank you
b/c we can take the address of a rvalue reference variable, such variables are themselves lvalues.
2) Can the same be said of lvalue references?

Addressability doesn't make something lvalue, it's the other way around: any named variable, regardless of its type, is an lvalue expression (when used as an expression), and any lvalue expression can appear to the right of the address-of operator (okay, except named bit fields - they are the only non-addressable lvalues).

even a string literal can be a lvalue, even though I've never seen it used on the left side of the = operator

as cppreference mentions, "left side of the = operator" is what "lvalue" meant in the extinct programming language CPL. Even in C they mean something else ("locator value"). Since you mention addressability, you can take an address of a string literal: const char (*p)[4] = &"abc";. You can also bind an lvalue reference to it: const char (&r)[4] = "abc";
Thanks for the correct syntax and explanations.

Earlier I had just given up on my naive attempt:
const char (*)[5] p = &"test"
(since visual studio kept reporting const char(*)[5] as the type).
Last edited on
Topic archived. No new replies allowed.