Do rvalue references allow dangling references?
Consider the below.
#include <string>
using std::string;
string middle_name () {
return "Jaan";
}
int main ()
{
string&& danger = middle_name(); // ?!
return 0;
}
This doesn't compute anything, but it compiles without error and demonstrates something that I find confusing: danger
is a dangling reference, isn't it?
Solution 1:
Do rvalue references allow dangling references?
If you meant "Is it possible to create dangling rvalue references" then the answer is yes. Your example, however,
string middle_name () {
return "Jaan";
}
int main()
{
string&& nodanger = middle_name(); // OK.
// The life-time of the temporary is extended
// to the life-time of the reference.
return 0;
}
is perfectly fine. The same rule applies here that makes this example (article by Herb Sutter) safe as well. If you initialize a reference with a pure rvalue, the life-time of the tempoary object gets extended to the life-time of the reference. You can still produce dangling references, though. For example, this is not safe anymore:
int main()
{
string&& danger = std::move(middle_name()); // dangling reference !
return 0;
}
Because std::move
returns a string&&
(which is not a pure rvalue) the rule that extends the temporary's life-time doesn't apply. Here, std::move
returns a so-called xvalue. An xvalue is just an unnamed rvalue reference. As such it could refer to anything and it is basically impossible to guess what a returned reference refers to without looking at the function's implementation.
Solution 2:
rvalue references bind to rvalues. An rvalue is either a prvalue or an xvalue [explanation]. Binding to the former never creates a dangling reference, binding to the latter might. That's why it's generally a bad idea to choose T&&
as the return type of a function. std::move
is an exception to this rule.
T& lvalue();
T prvalue();
T&& xvalue();
T&& does_not_compile = lvalue();
T&& well_behaved = prvalue();
T&& problematic = xvalue();
Solution 3:
danger
is a dangling reference, isn't it?
Not any more than if you had used a const &
: danger
takes ownership of the rvalue.