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

时间:2019-01-15 09:18:11

标签: c++ move

考虑以下代码段:

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

这个片段几乎就是我总是拥有的。

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

2 个答案:

答案 0 :(得分:2)

只需对您的课程稍作更改,即可它可以

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

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

答案 1 :(得分:2)

因为它不能被推断。该语言不知道拆卸int*涉及什么。也许您还有其他家务要执行。

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

此外,您正在重复代码中的逻辑。通过在移动构造函数和分配器中避免这些滑稽动作,您可以 “重用析构函数”,而只需交换指针,然后让移出对象的析构函数在时间到来时执行通常的操作:

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

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

(免责声明:我可能不记得有一种更惯用的方法来做到这一点,但您明白了。)

现在,样板更少了。因此,您可以看到,即使如果语言为您推导了move构造函数,它也根本不会涉及析构函数。