This question already has an answer here:
We cannot write int& ref = 40
because we need lvalue
on right side. But we can write const int& ref = 40
. Why is this possible? 40 is rvalue
instead lvalue
I know that this is an exception but why?
As Stroustrup says:
The initializer for a const T& need not be an lvalue or even of type T. In such cases:
[1] First, implicit type conversion to T is applied if necessary.
[2] Then, the resulting value is placed in a temporary variable of type T.
[3] Finally, this temporary variable is used as the value of the initializer.
So, when you type const int& ref = 40
, the temporary int variable is created behind the scenes, and ref is bound to this temporary variable.
There is a rule in the language that allows binding a const lvalue reference to an rvalue. The main reason for that rule is that, if it was not present, then you would have to provide different overloads of functions to be able to use temporaries as arguments:
class T; // defined somewhere
T f();
void g(T const &x);
With that rule in place you can do g(f())
, without it, to be able to do that you would have to create a different g
overload that takes an rvalue (and this is from a time where rvalue-references were not even in the language!)
why it is possible?
40 is a literal here. Constant references can be initialized with literals and temporaries to extend their life time. This can be done this way by a compiler:
int const& ans = 40;
// transformed:
int __internal_unique_name = 40;
int const& ans = __internal_unique_name;
Another situation is when you have a function, e.g:
void f( std::string const& s);
and you want to call it with
f( "something");
This temporary variable can be only bound to const reference.
You can bind an rvalue to a const reference. The language guarantees that the bound object lives until the scope of the reference ends and even calls the correct destructor statically. This is e.g. used in a ScopeGuard implementation (http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758?pgno=2) to have virtual-destructor-like behavior without paying for a virtual method call.
来源:https://stackoverflow.com/questions/22845167/const-reference-and-lvalue