Is it possible to std::move objects out of functions? (C++11)

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?


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, if X has a move constructor, x is moved.
• Otherwise, if X 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.


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:

  • a temporary, or
  • a single identifier naming something with automatic storage duration (like str above), or
  • std::move(something)

(So you could still have return std::move(str); to be explicit, but it's not necessary here.)