Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 535
Trevor Hickey Avatar asked Nov 29 '12 03:11

Trevor Hickey


1 Answers

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.

like image 110
billz Avatar answered Oct 14 '22 15:10

billz