Yanis.F
Yanis.F

Reputation: 684

Why isn't move operator just destructor + move constructor

Considering the following snippet :

class Foo
{
public:
    /* ... */
    Foo(Foo &&other);
    ~Foo();

    Foo &operator=(Foo &&rhs);

private:
    int *data;
};

Foo::Foo(Foo &&other)
{
    data = other.data;
    other.data = nullptr;
}

Foo::~Foo()
{
    delete data;
}

Foo &Foo::operator=(Foo &&other)
{
    if (this == &other) return *this;

    delete data;            /* SAME AS DESTRUCTOR */

    data = other.data;      /* SAME AS MOVE CONSTRUCTOR */
    other.data = nullptr;
    return *this;
}

This snippet is pretty much what I always end up having.

Why do we need a move operator if its behavior can be deduced ?
If this statement isn't true, in which case the move operator behave differently than just destructor + move constructor ?

Upvotes: 1

Views: 132

Answers (2)

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385254

Because it can't be deduced. The language doesn't know what is involved in tearing down your int*. Maybe you have other housekeeping to perform.

In fact, if you're writing a move constructor, you'll usually have other housekeeping to perform, because if all you are doing is deleteing dynamic memory, you should have been using a smart pointer and wouldn't need to write your own move constructor at all.

Furthermore, you're repeating logic in your code. You can "re-use the destructor" by avoiding these antics in your move constructor & assigner, simply swapping pointers instead, and let the moved-from object's destructor do what it usually does when the time comes:

Foo::Foo(Foo&& other)
   : data(nullptr)
{
    *this = std::move(other);
}

Foo& Foo::operator=(Foo&& other)
{
    std::swap(this->data, other.data);
    return *this;
};

(Disclaimer: there's probably a more idiomatic way to do this that I can't remember, but you get the point.)

Now there's much less boilerplate. So you can see that, even if the language deduced move constructors for you, it wouldn't involve a destructor at all.

Upvotes: 2

Caleth
Caleth

Reputation: 62984

With a small change to your class, it can.

class Foo
{
public:
    /* ... */
    // deleted copy constructor and copy assignment
    // generated destructor, move constructor and move assignment

private:
    std::unique_ptr<int> data;
};

Upvotes: 2

Related Questions