For some reason I didn't manage to find this exact question. Why is it allowed to bind an rvalue
to const lvalue reference
, although it is impossible to to the same without the const
?
I do understand that the lifetime of the rvalue gets an extension somehow (in the first case) , but if so, why would the compiler disallow changing that 'rvalue', which is not really a temporary object anymore.
For example, consider the following code:
int main(){
int &i=3; //produces error
const int&j =3; //compiles
return 1;
}
An lvalue const reference can bind to an lvalue or to an rvalue. The syntax for a reference to an rvalue of type T is written as T&& . An rvalue reference refers to a movable value—a value whose contents we don't need to preserve after we've used it (for example, a temporary).
If we take a const rvalue reference, it can be used with the f(const T&&) and f(const T&) , but not with any of the non- const references. By the way, don't return const values from a function, because you make it impossible to use move semantics.
An lvalue is an expression that yields an object reference, such as a variable name, an array subscript reference, a dereferenced pointer, or a function call that returns a reference. An lvalue always has a defined region of storage, so you can take its address. An rvalue is an expression that is not an lvalue.
Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.
You may find the following article useful:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0345.pdf
I might be entirely wrong here, but this is how I rationalise it. An rvalue is constant, it cannot be changed. you cannot change the integer 5, fact. So when you bind the references the lvalue will have to be const. Otherwise your compiler will throw an error:
obj & a1 = bar();
invalid initialization of non-const reference of type ‘obj&’ from an rvalue of type ‘obj’
using g++
The only way to safely bind an rvalue to an lvalue is either by marking the lvalue as const, or using a mutable rvalue reference &&
(introduced in C++11 believe?)
struct obj {
};
obj bar() {
obj x;
return x;
}
int main() {
const obj & a1 = bar();
obj && a2 = bar();
return 0;
};
If you're asking about
void f(const int&);
f(1);
versus
void g(int&);
g(1);
the answer is to think about what happens if g
looks like this:
void g(int& r) {
++r;
}
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