2

Consider this kind of a function:

std::vector<int> generateVector() {
    return std::vector<int>(10, 0);
}

Are there any benefits in calling generateVector() like this:

std::vector<int> v = std::move(generateVector());

..or is this kind of a move optimization now automatically done by the compiler?

user2061057
  • 962
  • 1
  • 9
  • 20
  • Ask yourself why they are called _rvalue references_!! – Lightness Races in Orbit Mar 31 '15 at 15:09
  • Ok, now I have asked myself that. As Scott Meyers argued that you should use even int x = std::move(y) I got really confused and hence this question. I don't see the difference between these cases. And this is not a duplicate, a completely different scenario in that "possible duplicate" question. – user2061057 Mar 31 '15 at 15:29
  • @user2061057 `or is this kind of a move optimization now automatically done by the compiler?`. The duplicate answer states: *All return values are already moved or else optimized out, so there is no need to explicitly move with return values.* Isn't that a direct answer to your question? How isn't this a duplicate? – Julian Mar 31 '15 at 15:36
  • Are we talking about duplicate answers or duplicate questions? The question is different and std::move is used in a different way. – user2061057 Mar 31 '15 at 15:39
  • I can still mark this as duplicate if it makes you happy. – user2061057 Mar 31 '15 at 15:46

3 Answers3

8

Neither:

  • There's no benefit.

  • The compiler does nothing special except for compiling C++. It will probably try to do this well.

Fortunately, the expression generateVector() is already an rvalue, so v will be constructed with the move constructor, but in fact your declaration of v and your definition of generateVector are subject to copy elision, so that the construction may be treated as equivalent to:

std::vector<int> v(10, 0);

In other words, the language rules explicitly allow for copy constructors not to be called under these circumstances, even if they have side effects.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 2
    Having had that topic here before, I remember that then someone argued that using std::move would if anything make the code worse as copy elision is preferable to move construction in terms of performance. – BitTickler Mar 31 '15 at 15:02
  • 2
    @user2225104: I think that referred only to the return statement. I.e. `return std::move(std::vector(10, 0));` would be a strict pessimisation. – Kerrek SB Mar 31 '15 at 15:09
7

The purpose of std::move is to make an lvalue into an rvalue. In your case, generateVector() is already an rvalue, so it's redundant.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • 1
    I **wont** say it is *"redundant"* (which implies it has no effect at all, which may be wrong). I'd rather say it may prevent certain optimization, such as move-elision. So it is *better* if you dont write `std::move`. – Nawaz Mar 31 '15 at 15:06
6

The result of a function call that returns an object is already an rvalue, so applying std::move has no benefit.

In fact it can be a pessimisation: without std::move, the variable is directly initialised from a temporary, and so the temporary (and the move) can be elided.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644