Is move semantics just a shallow copy and setting other's pointers to null?

2.3k views Asked by At

I've been reading about move semantics in C++, and in the explanations people give a lot of analogies to help simplify it, and in my head all I can see is that what people call "moving" as opposed to "copying" is just a shallow copy of the object and setting any pointers in the "moved-from" object to null. Is this basically the gist? Shallow copy and set other's pointers to null?

2

There are 2 answers

0
Richard Hodges On

Shallow copy and set other's pointers to null?

Shallow copy - yes. Setting other's pointers to null - not always.

The minimum requirement is that the moved-from object is in an "undefined but valid state", which is to say that you can reassign to it, move it again or delete it without causing the program to fail, but perform no other state-dependent operation on it. This means that it's perfectly valid in general to implement move-assignment in terms of std::swap.

Some objects define a stronger contract. One of these is std::unique_ptr. Moving-from one of these will result in it containing null, but this is explicitly documented.

0
eerorika On

Is move semantics just a shallow copy and setting other's pointers to null?

It can be, if the pointers being null satisfies the class invariant. That is to say: If the object with null pointers is a valid state.

So, I would give a longer description: Move constructor and assignment operator perform a shallow copy, and clean up the moved from object into a state that satisfies the class invariant.

Also remember that in the case of move assignment, you must remember to handle the pointer that would be overwritten by the swallow copy.

If the class owns pointed objects for example, the invariant requires that no two objects own the same object. There are at least three ways to implement this:

  • Set the pointer to null
  • Construct a new object
  • Swap the pointers with the moved to object (in case of move constructor, this is essentially same as one of the previous options since the pointer is initially uninitialized unless one of the previous is first performed, but with move assignment this handily takes care of the object previously pointed by the moved-to object).

It is sometimes necessary to also set non-resource data such as size field or similar to match the new state of the object if the invariant so requires. There are other resources that the object might hold and must also be cleaned up besides owning pointers to memory, for example file descriptors.