For some time this has been confusing me. And I've not been able to find a satisfactory answer thus far. The question is simple. When does a move assignment operator
get called, and when does a move constructor operator
get called?
The code examples on cppreference.com yield the following interesting results:
The move assignment operator:
a2 = std::move(a1); // move-assignment from xvalue
The move constructor:
A a2 = std::move(a1); // move-construct from xvalue
So has it do to with which is implemented? And if so which is executed if both are implemented? And why is there the possibility of creating a move assignment operator overload at all, if it's identical anyway.
Move constructor moves the resources in the heap, i.e., unlike copy constructors which copy the data of the existing object and assigning it to the new object move constructor just makes the pointer of the declared object to point to the data of temporary object and nulls out the pointer of the temporary objects.
The move constructor and move assignment operator are simple. Instead of deep copying the source object (a) into the implicit object, we simply move (steal) the source object's resources. This involves shallow copying the source pointer into the implicit object, then setting the source pointer to null.
A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: &&. This topic builds upon the following C++ class, MemoryBlock , which manages a memory buffer.
The subtle difference is, if you create with a copy or move semantic a new object based on an existing one, that the copy semantic will copy the elements of the resource, that the move semantic will move the elements of the resource.
A move constructor is executed only when you construct an object. A move assignment operator is executed on a previously constructed object. It is exactly the same scenario as in the copy case.
Foo foo = std::move(bar); // construction, invokes move constructor
foo = std::move(other); // assignment, invokes move assignment operator
If you don't declare them explicitly, the compiler generates them for you (with some exceptions, the list of which is too long to be posted here).
See this for a complete answer to when the move member functions are implicitly generated.
When does a move assignment operator get called
When you assign an rvalue to an object, as you do in your first example.
and when does a move constructor operator get called?
When you initialise an object using an rvalue, as you do in your second example. Although it isn't an operator.
So has it do to with which is implemented?
No, that determines whether it can be used, not when it might be used. For example, if there's no move constructor, then construction will use the copy constructor if that exists, and fail (with an error) otherwise.
And if so which is executed if both are implemented?
Assignment operator for assignment, constructor for initialisation.
And why is there the possibility of creating a move assignment operator overload at all, if it's identical anyway.
It isn't identical. It's invoked on an object that already exists; the constructor is invoked to initialise an object which previously didn't exist. They often have to do different things. For example, assignment might have to delete something, which won't exist during initialisation.
This is the same as normal copy assignment and copy construction.
A a2 = std::move(a1);
A a2 = a1;
Those call the move/copy constructor, because a2
doesn't yet exist and needs to be constructed. Assigning doesn't make sense. This form is called copy-initialization.
a2 = std::move(a1);
a2 = a1;
Those call the move/copy assignment operator, because a2
already exists, so it doesn't make sense to construct it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With