1

This question is in the context of c++11.

When a variable which is allocated on the stack is returned from a function, is the copy optimized out if the object defines a move constructor?

I have this piece of code, the move constructor and the function I described above:

MyBigObject(MyBigObject&& other) {
  // code elided
}

MyBigObject createTheObject() {
  MyBigObject emptyObj;
  // initialize obj with stuff
  return emptyOBj;
}

Does this definition of the move constructor mean that all returns by values are converted automatically to 'moves'? Or is the copy going to be optimized out by some other mechanism other than move?

How would this code behave if there were no move constructor defined? In that case does the full copy happen instead?

2 Answers2

6

Does this definition of the move constructor mean that all returns by values are converted automatically to 'moves'?

Yes. If you return a local variable, it's treated as an rvalue and the return value is initialised by moving it, if it has a move constructor.

Or is the copy going to be optimized out by some other mechanism other than move?

The move or copy can also be elided, by an optimisation called return value optimisation. This happens in various situations, including returning a local variable. The variable is constructed directly into the caller's stack frame, so that there's no need to move or copy anything on return.

How would this code behave if there were no move constructor defined? In that case does the full copy happen instead?

Yes, if there is no move constructor, then moving is done by copying. Again, this can often be elided when returning a value from a function.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • +1 I like to think of it as an automatic hierarchy of "move semantics" from best to worst: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Moving%20from%20local%20values – Howard Hinnant Feb 23 '14 at 23:54
  • In particular, this is NRVO, which is distinct from RVO for random reasons. – Yakk - Adam Nevraumont Feb 24 '14 at 05:23
  • 1
    @Yakk: I'm not sure what you mean by "distinct". Those two non-standard terms describe exactly the same optimisation; it's just permitted for a different reason depending on whether the return value is a named automatic variable or a temporary. – Mike Seymour Feb 24 '14 at 05:29
5

Does this definition of the move constructor mean that all returns by values are converted automatically to 'moves'?

No, usually what happens is named return value optimization (NRVO), a form of copy elision, which means there is nothing to move. This applies to C++03 as well as C++11.

Iff the compiler cannot perform copy elision, then yes, emptyObj will be moved into the object on the caller side. This only applies since C++11.

See what are copy elision and return value optimization

Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480