This program tries to move a string out of a function and use it for the construction of another string:
#include
#include
#i
That Get_String
function binds an rvalue reference to a function-local object. Rvalue references are useful for things that are about to be destroyed, but just as bad as lvalue references for things that have already been destroyed.
To move a local object out of a function, you just return by class type:
std::string Get_String(void) {
std::string str{"hello world"};
return str;
}
If the compiler doesn't manage to eliminate the copy/move entirely, then the return value that the caller gets will be constructed using a move constructor, not a copy constructor, as long as the return expression is:
str
above), orstd::move(something)
(So you could still have return std::move(str);
to be explicit, but it's not necessary here.)
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.