Given this example,
X foo ()
{
X x;
return x;
}
the following behavior is guaranteed:
• If
X
has an accessible copy or move constructor, the compiler may
choose to elide the copy. This is the so-called (named) return value
optimization ((N)RVO), which was specified even before C++11 and is
supported by most compilers.
• Otherwise, ifX
has a move constructor,x
is moved.
• Otherwise, ifX
has a copy constructor,x
is copied.
• Otherwise, a compile-time error is emitted.
Note also that returning an rvalue reference is an error if the returned object is a local nonstatic object:
X&& foo ()
{
X x;
return x; // ERROR: returns reference to nonexistent object
}
An rvalue reference is a reference, and returning it while referring to a local object means that you
return a reference to an object that doesn’t exist any more. Whether std::move()
is used doesn’t
matter.
std::move()
doesn’t really move object; it only turns lvalues into rvalues.