为什么移动运算符不只是析构函数+移动构造函数

Why isn't move operator just destructor + move constructor

考虑以下代码段:

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;
}

这段代码几乎就是我最终得到的。

如果可以推断其行为,为什么我们需要移动运算符?
如果此语句不正确,在这种情况下,移动运算符的行为不同于析构函数 + 移动构造函数 ?

只要对您的 class 稍作改动,就可以

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

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

因为无法推导。该语言不知道拆除您的 int* 涉及什么。也许您还有其他家务需要执行。

事实上,如果您正在编写一个移动构造函数,您 通常 需要执行其他内务处理,因为如果您所做的只是 delete动态内存,你应该一直使用智能指针,根本不需要编写自己的移动构造函数。

此外,您在代码中重复逻辑。您 可以 "re-use the destructor" 通过在您的移动构造函数和分配器中避免这些滑稽动作,只需交换指针,并让移出对象的析构函数在时机成熟时执行它通常执行的操作:

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

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

(免责声明:可能有更惯用的方法,我不记得了,但你明白了。)

现在样板文件少了很多。所以你可以看到,即使 if 语言为你推导出移动构造函数,它也根本不会涉及析构函数。