Can you implement the move constructor via move operator?

In order to avoid code repetition, it makes sense to implement certain functions using other functions which already exist. The move constructor sounds like a pretty good candidate for this, since the move operator is already there (at least it should be if we follow the rule of 5).

So can we implement the move constructor using the move operator?

The main obvious difference is that when you are calling the move constructor, the object you are constructing is coming from a null state. However, if you are using the move operator, the object you are moving into might not be in a null state, and might thus have to be nullified.

Why does it have to be nullified?

One concept which isn’t nearly as widely accepted as I would like it to be is that the moved-from object should be in a null but valid state. This isn’t just for the sake of creating a standard and being neat, but has a rather practical reason.

Say you wrote your move operator without nullifying the moved-from object like this:

Foo& operator= (Foo&& other) noexcept
{
    swapFunction(data, other.data);
    return *this;
}

If “data” contained a large object in memory, this would then be transferred into the “other” object that is being moved from. This wouldn’t be good, since it’s a reasonable expectation that the moved-from object is empty and can be ignored/discarded (ie in a null state). The moved from object also has to be in a valid state, in case a destructor is called on it.

So a correct way would be this:

Foo& operator= (Foo&& other) noexcept
{
    swapFunction(data, other.data);
    nullify(other.data);
    return *this;
}

On the other hand, when you are writing a move constructor, the object that is being constructed starts in a null state, and you don’t have to nullify the data being moved into. This means that if you implemented a move constructor using a move operator, you might be doing an unnecessary data nullification.

TLDR: You should avoid implementing the move constructor using the move operator, unless you are sure that the data nullification is (and will be) very cheap.

Leave a Reply

Your email address will not be published. Required fields are marked *