Return by value in rvalue reference
I am looking into rvalue references and I have doubts about the following code:
string func() {
return "Paul";
}
int main()
{
string&& nodanger = func();
// The lifetime of the temporary is extended
// to the life-time of the reference.
return 0;
}
Question: what is returned func()
?
I believe this is happening:
- func returns prvalue "Paul" (is it const char * due to rvalue-> pointer conversion?)
- the string object is implicitly constructed (which ctor is used?)
- binds to "nodanger" due to link folding rules (does this behave differently than a string and a normal link?)
source to share
The function func()
returns a std::string
prvalue. The constructor used to build std::string
is
basic_string( const CharT* s,
const Allocator& alloc = Allocator() );
This prvalue is bound to the rvalue reference nodanger
, which extends the lifetime to match the reference itself. The link does not come into play here.
does it behave differently than a normal link
string&
?
The code will not compile if nodanger
was string&
because you can not communicate with links rvalues const lvalue. The lifespan extension behavior in your example is identical to the following case
std::string const& nodanger = func();
source to share
There is definitely a lot of confusion here. I suppose there middle_name()
should be func()
.
Question: what does func () function return?
It returns a string
(which I will count std::string
). This return object is initialized with an expression of "Paul"
type "array of 5 const
char
". The constructor used is as follows:
basic_string( const CharT* s,
const Allocator& alloc = Allocator() );
To call this function, a string literal must undergo an implicit conversion between strings (taking us from const char[5]
to const char*
.
An expression func()
is a prvalue expression (a subset of rvalue expressions) because it returns a value. Here's how the standard defines it:
A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference for a function type, an xvalue if the result type is an rvalue reference for an object type, and a prvalue otherwise.
It doesn't make sense to say that "returns a prvalue". "Prvalue" is not an object or type. This is a category of expression. The expression that calls func
is prvalue.
An rvalue reference binds to an object std::string
that was returned from a function. There are no links to crumbling here. If the reference was an lvalue reference instead, your code will not compile because a non- const
lvalue reference can not bind to an rvalue expression.
source to share