Reputation: 15756
It's illegal to:
constexpr int& v = 1;
since v
cannot 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
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
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
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
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