对于什么是需要的Unique Pointers中的移动构造函数和移动赋值构造函数?

时间:2015-05-22 17:27:02

标签: c++ c++11 smart-pointers move-semantics unique-ptr

我有一个unique_ptr的简化示例。我想知道在唯一指针中需要移动构造函数和移动赋值运算符是什么? 如果我理解移动构造函数(并传递rvalues),那么这两行代码应该是相同的。

UniquePointer<T> a(new T);
UniquePointer<T> a(UniquePointer<T>(new T));

这是简化的UniquePointer代码:

template<typename T> class UniquePointer {
    T* m_ptr;
public:
    UniquePointer(const UniquePointer&) = delete;
    UniquePointer& operator=(const UniquePointer&) = delete;
    UniquePointer(UniquePointer&& rhs);
    UniquePointer& operator=(UniquePointer&& rhs);
    UniquePointer(T* ptr) : m_ptr(ptr) { }
    T* operator->() const { return m_ptr; }
    T& operator*() const { return *m_ptr; }
    T* get() const { return m_ptr; }
    ~UniquePointer() { delete m_ptr; }
};

3 个答案:

答案 0 :(得分:3)

首先调用常规构造函数UniquePointer(T* ptr)(而不是移动构造函数)。当您传入类型UniquePointer(UniquePointer&& rhs)的右值时,第二次调用移动构造函数UniquePointer,并删除复制构造函数。

当你做

时,你也需要移动构造函数
UniquePtr<T> ptr = std::move(some_old_unique_ptr);

在这种情况下,您需要std::move来自旧版本,因为旧版本是lvalue。在已构造的对象上调用移动赋值运算符

ptr = std::move(yet_another_ptr); // invokes the move assignment operator

至于为什么需要它们,这是因为设计。这些对象是不可复制的,因此您需要移动它们。

答案 1 :(得分:2)

如果您需要将所有权从一个范围转移到另一个范围,则需要一个单独的对象。因为你不能(并且不想)复制unique_ptr,这意味着你需要移动它。例如,从函数返回unique_ptr时。

std::unique_ptr<Foo> func()
{
    std::unique_ptr<Foo> ptr(new Foo);
    ...
    return ptr;
}

这需要移动构造函数或复制构造函数。另一个常见用例是从构造函数参数初始化类成员。

class Widget
{
public:
    Widget(std::unique_ptr<Foo> _foo_ptr)
       :foo_ptr(std::move(_foo_ptr))
    {}
private:
    std::unique_ptr<Foo> foo_ptr;
};

答案 2 :(得分:0)

std::unique_ptr需要移动构造函数和移动赋值运算符,因为它是一个不可复制且因此唯一的对象。由于它是不可复制的,因此需要有一种方法将其传递给事物,因此移动操作可以解决这个问题。