35

I have a very basic question: is it a good idea to return a std::vector<A> using std::move? For, example:

class A {}; std::vector<A> && func() { std::vector<A> v; /* fill v */ return std::move(v); } 

Should I return std::map, std::list.. etc... in this way?

5
  • 4
    This won't compile. Commented May 19, 2017 at 9:06
  • 7
    Just return it by value. Commented May 19, 2017 at 9:08
  • std::vector<A> & v; ?? are you sure about that ? Commented May 19, 2017 at 9:16
  • 1
    Returning by value should be considered preferable. You will get return value optimization, whereas with moving you will incur a move. Commented May 19, 2017 at 9:21
  • I meant std::vector<A> v, without & Commented May 19, 2017 at 9:32

3 Answers 3

44

You declare a function to return by r-value reference - this should almost never be done (if you return the local object by reference, you will end up with a dangling reference). Instead declare the function to return by value. This way the caller's value will be move constructed by the r-value returned by the function. The returned value will also bind to any reference.

Secondly, no, you should not return using an explicit std::move as this will prevent the compiler to use RVO. There's no need as the compiler will automatically convert any l-value reference returned to an r-value reference if possible.

std::vector<A> func() { std::vector<A> v; /* fill v */ return v; // 'v' is converted to r-value and return value is move constructed. } 

More info:

Sign up to request clarification or add additional context in comments.

4 Comments

This is not true until C++14. In C++11, when copy constructor is a deleted function, you need to explicitly std::move because RVO optimization is not guaranteed. For this reason, the compiler requires to have a copy constructor so that he will chose to copy when he decides he can't apply RVO
@HAL9000 This answer is about std::vector, std::map, and std::list (see the question), which neither have their copy ctor deleted. There are of course other objects that need an explicit std::move, e.g. std::unique_ptr etc. Using an explicit move represent resource ownership transfer for cases where copying is disallowed by design, not optimization of return values. And btw, basically all compilers supported RVO during the C++11 era, even though it was not guaranteed by the standard :)
@Snps I agree with the first part, I didn't pay enough attention to the question. For the RVO support, you didn't get the point: the language considers it an error when the copy constructor is a deleted function, because RVO support is not guaranteed, it doesn't matter if a compiler supports it.
@HAL9000 If the copy ctor was deleted by design and a user defined move ctor is present, then yes you would have to explicitly use std::move in C++11 if returning by value (if the move ctor is not user defined in this case, it would not be implicitly defined and you would get an error anyway). This all seems to be the exceptional case though.
3

No, it's not. This will in fact prevent copy elision in some cases. There is even a warning in some compilers about it, called -Wpessimizing-move.

In agreement with other answers, just return it by value, changing the return type to simply be std::vector<A>, and the compiler will take care of calling the move constructor when needed.

You could take a look at this post I just found, which seems to explain it in much detail (although I haven't read it through myself): https://vmpstr.blogspot.hu/2015/12/redundant-stdmove.html

3 Comments

While correct on the pessimising move, this answer is dangerous because it fails to address the fact that the returned reference will be dangling.
You don't think saying "just return it by value" kind of addresses this?
I consider it a tad too subtle: it can be interpreted as "just return the value without std::move" as well as "change the return type."
1

Both gcc and clang compiler with enabled optimization generate same binary code for both case when you return local variable and when you write std::move(). Just return a value.

But using && and noexcept specifier is useful if you create moving constructor and moving operator= for your custom class

1 Comment

This has nothing to do with optimisations, really. The standard requires moving to be tried first in this case. Also, this answer is dangerous because it fails to address the fact that the returned reference will be dangling.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.