This program tries to move a string out of a function and use it for the construction of another string:
#include <iostream>
#include <string>
#include <utility>
std::string && Get_String(void);
int main(){
std::string str{Get_String()};
std::cout << str << std::endl;
return 0;
}
std::string && Get_String(void){
std::string str{"hello world"};
return std::move(str);
}
The program compiles, but segfaults upon execution.
This was my rationale: Get_String
will create a local string. A copy of that string will need to be made and returned before the string goes out of scope. That copy will be used to construct the string in main. However, If I moved the the string out of the function, no copy would need to be made.
In an attempt to understand move semantics, could someone explain why what I'm doing, probably makes no sense. Is it possible to move objects out of a function?
EDIT:
It compiles and runs correctly if I change the function signature from:
std::string && Get_String(void);
to
std::string Get_String(void);
Is it still more efficient to move the string during the return in this case?
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:
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,
the following behavior is guaranteed:
Note also that returning an rvalue reference is an error if the returned object is a local nonstatic 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.