This question already has an answer here:
-
Using std::move() when returning a value from a function to avoid to copy
3 answers
Let there be a class A
with a move constructor. Consider this:
A get()
{
A a;
return std::move( a );
}
// later in the code
A aa = get();
Here the explicit call to std:move
forces the move constructor of A
to be called thus it might inhibit the return value optimization in while calling get()
. Thus it is said the a better implementation of get()
would be this:
A get()
{
A a;
return a;
}
But the return value optimization is not a part of C++11 standard, so WHAT IF the compiler, by some reason, decides not to perform return value optimization while calling get()
. In this case a copy constructor of A
will be called while returning in get()
right?
So isn't the first implementation of get()
more pereferible??
A compiler should use a move constructor, but I didn't see an obligation in the standard :
It's always said "Copy/move constructor" in the section concerning temporary objects
standard ISO/IEC 14882:2011 C++ :
"
12.1/9
A copy constructor (12.8) is used to copy objects of class type. A move constructor (12.8) is used to move
the contents of objects of class type.
12.8/32
When the criteria for elision of a copy operation are met or would be met save for the fact that the source
object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to
select the constructor for the copy is first performed as if the object were designated by an rvalue. If overload
resolution fails, or if the type of the first parameter of the selected constructor is not an rvalue reference to
the object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as an
lvalue. [ Note: This two-stage overload resolution must be performed regardless of whether copy elision will
occur. It determines the constructor to be called if elision is not performed, and the selected constructor
must be accessible even if the call is elided. — end note ]
"
lvalue = T &
rvalue = T &&
So, It says that first, the compiler will look if it find a move constructor, then, it will look for a move constructor.
Thus, if your compiler is conform to the standard, it will call the move constructor.
I append just that which is interesting:
"
12.8/31
When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class
object, even if the copy/move constructor and/or destructor for the object have side effects.
"
...So even if there is side effects in these constructors/destructors, they can be skipped