Consider a type T supporting the default move semantics. Also consider the function below:
T f() {
T t;
return t;
}
T o = f();
In the old C++03, some non-optimal compilers might call the copy constructor twice, one for the "return object" and one for o
.
In c++11, since t
inside f()
is an lvalue, those compilers might call the copy constructor one time as before, and then call the move constructor for o.
Is it correct to state that the only way to avoid the first "extra copy" is to move t
when returning?
T f() {
T t;
return std::move(t);
}
No. Whenever a local variable in a
return
statement is eligible for copy elision, it binds to an rvalue reference, and thusreturn t;
is identical toreturn std::move(t);
in your example with respect to which constructors are eligible.Note however that
return std::move(t);
prevents the compiler from exercising copy elision, whilereturn t
; does not, and thus the latter is the preferred style. [Thanks to @Johannes for the correction.] If copy elision happens, the question of whether or not move construction is used becomes a moot point.See 12.8(31, 32) in the standard.
Note also that if
T
has an accessible copy- but a deleted move-constructor, thenreturn t;
will not compile, because the move constructor must be considered first; you'd have to say something to the effect ofreturn static_cast<T&>(t);
to make it work: