Is the movement of the object guaranteed when it is returned?

I know that by passing an object by function value, the move constructor is always called if there is one, if copying is not required. How about returning an object by value?

For example, let's say we have a class Foo that has a move constructor, and we have a function that returns a Foo object.

 Foo g() { Foo f; // do something with f return f; } 

If we assume that there is no RVO, a move constructor, which is supposed to be called?

Update: I think I did not show my intention clearly. I just want to know that in the worst case scenario I can move an object that is not copied. Either RVO or NRVO happens, I'm happy. And I must also say that the move constructor and move destination are not deleted and are executed properly.

+7
source share
3 answers

Yes. See [Class.copy] p32

When the criteria for performing the copy operation are fulfilled or are fulfilled, except for the fact that the source object is a parameter of the function, and the object to be copied is determined by the value of lvalue, the overload resolution to select the constructor for the copy is first executed as if the object was designated rvalue. If the overload resolution failure or the type of the first parameter of the selected constructor is not an rvalue reference to the type of objects (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue. [Note. This two-stage overload resolution should be performed regardless of whether copying occurs. It defines the calling constructor if elision fails, and the selected constructor must be available, even if the call is canceled. - final note]

+4
source

In this case, since the return value has the name ( f ), it will apply to the NRVO (named return value).

So, the technical answer, based only on formulations, is that the lack of RVO will not prevent copying, since NRVO can still resolve it.

The past, I believe that the choice between move / copy of the return value can / will depend on the definition of Foo - there are certain times when it will be copied instead of moving, for example, if you explicitly deleted the move constructor and move assignment operators, or you did not define the construct displacement / assignment, and it cannot be synthesized implicitly.

Edit: [answer to edited question]: having a move constructor still does not guarantee that the result will be moved. One obvious example would be if you removed the move assignment operator and assigned the result (rather than using it to initialize). In this case, the operator of assigning remote operations will prevent the return value from being moved.

To answer what you may have received, however, the general rule is that the move will be done if possible, and it will be returned to copying if and only if something does not allow the result to be moved.

+2
source

The rule is that whenever copy permission is allowed but does not occur, the move constructor will be used if it is available, and otherwise the copy constructor will be used.

The exact behavior is determined by [class.copy]/32 :

When the criteria for performing the copy operation are fulfilled or are fulfilled, except for the fact that the source object is a parameter of the function, and the object to be copied is determined by the value of lvalue, the overload resolution to select the constructor for the copy is first executed as if the object was designated rvalue. If the overload fails, or if the type of the first parameter of the selected constructor is not an rvalue reference to the type of the object (possibly with qualification cv), overload resolution is performed again, considering the object as an lvalue.

+1
source

All Articles