3

I am quite puzzled by the std::move stuff. Assume I have this piece of code:

string foo() {
  string t = "xxxx";
  return t;
}

string s = foo();

How many times the string constructor is called? Is it 2 or 3? Is the compiler going to use move for this line?

string s = foo();

If so, in the function I am not even returning rvalue reference, so how could the compiler invoke the move constructor?

WhatABeautifulWorld
  • 3,198
  • 3
  • 22
  • 30

1 Answers1

4

It depends on the compiler. In this case, the standard requires that there will be at least one constructor call. Namely, the construction of t.

But the standard allows the possibility of two others: the move-construction of the value output of foo from t, and the move-construction of s from the value output of foo. Most decent compilers will forgo these constructors by constructing t directly in the memory for s. This optimization is made possible because the standard allows these constructors to not be called if the compiler chooses not to.

This is called copy/move "elision".

If so, in the function I am not even returning rvalue reference, so how could the compiler invoke the move constructor?

You seem to be laboring under the misconception that && means "move", and that if there's no && somewhere, then movement can't happen. Or that move construction requires move, which also is not true.

C++ is specified in such a way that certain kinds of expressions in certain places are considered valid to move from. This means that the value or reference will attempt to bind to a && parameter before binding to a & parameter. Temporaries, for example, will preferentially bind to a && parameter before a const& one. That's why temporaries used to construct values of that type will be moved from.

If you have a function which returns a value of some type T, and a return expression is of the form return x, where x is a named variable of type T of automatic storage duration (ie: a function parameter or stack variable), then the standard requires that this return expression move construct the returned value from x.

The return value of foo is a temporary. The rules of C++ require that temporaries bind to && parameters before const&. So you get move construction into s.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • What if we assume the compiler doesn't do any optimization? – WhatABeautifulWorld Sep 05 '13 at 03:54
  • @WhatABeautifulWorld: Then it would be the one constructor I said would happen plus the two optional ones that I said were optional. – Nicol Bolas Sep 05 '13 at 03:57
  • do I have to change the function definition for foo, to be able to move it? I am thinking of: string&& foo() {...} Otherwise how could the compiler know? String is just an example, in reality I have my own obj... – WhatABeautifulWorld Sep 05 '13 at 04:01
  • @WhatABeautifulWorld NO. Don't ever return rvalue references. Rvalue references are references, and in C++ you were never allowed to return a reference to a local variable http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794. Rvalue references are still references; they are not magical. – R. Martinho Fernandes Sep 05 '13 at 15:33