Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding rvalue to const lvalue reference

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;
}
like image 322
Eliran Abdoo Avatar asked Nov 29 '16 18:11

Eliran Abdoo


People also ask

Can lvalue reference bind rvalue?

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

Can rvalue be const?

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.

Is an rvalue reference an lvalue?

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.

What is R value reference in C++?

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.


2 Answers

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;
};
like image 183
TomJ Avatar answered Sep 18 '22 03:09

TomJ


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;
}
like image 45
Pete Becker Avatar answered Sep 21 '22 03:09

Pete Becker