Vinícius
Vinícius

Reputation: 15756

For what reason would it be necessary to bind a const lvalue reference to an rvalue?

It's illegal to: constexpr int& v = 1; since vcannot be resolved at compile-time, which makes sense.

Now it surprised me that const int& v = 1; is legal.

However I cannot see how this is different from const int v = 1;.

In what case would it be necessary to bind a const lvalue reference to an rvalue?

Upvotes: 3

Views: 825

Answers (4)

NathanOliver
NathanOliver

Reputation: 181068

constexpr int& v and const int& v are not the same thing. constexpr int& v means create a reference to an int and that reference is a constexpr. You can't bind that to a temporary because lvalue references to mutable object are not allowed to bind to a temporary.

const int& v on the other hand means create a reference to a const int. This is allowed to bind to a temporary since you cannot modify the state of the temporary.

In what case would it be necessary to bind a const lvalue reference to an rvalue?

Pre C++11, this was the only way to capture a reference to a temporary. For example

std::vector<int> make_vec(int size) { return std::vector<int>(size); }

const std::vector<int>& foo = make_vec(1000);

In the above code, ignoring any sort of optimization, this is the only way to access the vector that make_vec returns without making a copy of it. This was/is very important as it helps to prevent a lot of copies that C++'s value semantics naturally creates.

Post C++11 it's not needed as much as we now have rvalue references that allow you to bind a reference to a temporary, and you can modify it since they are typically not const.

Upvotes: 3

C. R. Ward
C. R. Ward

Reputation: 93

I'll take a guess at the answer: It won't seem that either the membership access operator (.) or the membership dereference operator (->) is defined for this statement const int& v = 1;, so the statement just has to have that effect, even though it shouldn't really be able to have that outcome.

On the other hand, if you were to say, const std::string& s = 1;, this should not work unless operator= is overloaded to make it have the effect you would want.

A problem with *this can be caught at compile time, but a problem with a bad integer value or pointer value usually isn't.

Upvotes: 0

eerorika
eerorika

Reputation: 238491

For what reason would it be necessary to bind a const lvalue reference to an rvalue?

While not necessary per se, this is very useful when calling functions with lvalue reference arguments:

class foo;

void bar(const foo&);

bar({}); // lvalue reference bound to rvalue

Upvotes: 0

Sneftel
Sneftel

Reputation: 41542

Languages like C++ are designed in terms of what they can do, more than they are designed in terms of what they can't. So your question shouldn't be "in what case is this necessary" [never], but "what features of the language make this possible?" In this case, the main feature is what is known as "the most important const", whereby a const reference can be bound to an rvalue, extending its lifetime until the end of the reference's scope. This is sometimes useful for rvalues that are returned from function calls or other expressions. But integer literals are also rvalues. It was more practical to specify the behavior of binding a const reference to any rvalue, than to come up with more stringent rules about what kind of rvalues were worthy of such a treatment.

Upvotes: 2

Related Questions