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?
Not just a copy; it is also a const copy. So you cannot modify it, invoke any non-const members from it, or pass it as a non-const parameter to any function. If you want a modifiable copy, lose the const decl on protos .
Such a reference is called an lvalue reference to a const value (sometimes called a reference to const or a const reference). In the above program, we bind const reference ref to modifiable lvalue x . We can then use ref to access x , but because ref is const, we can not modify the value of x through ref .
- const references allow you to specify that the data referred to won't be changed. A const reference is actually a reference to const. A reference is inherently const, so when we say const reference, it is not a reference that can not be changed, rather it's a reference to const.
Passing by const reference is a safer option if you work on a team without comprehensive performance regression tests. You will get bitten by this sooner or later.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With