我有一个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; }
};
答案 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
需要移动构造函数和移动赋值运算符,因为它是一个不可复制且因此唯一的对象。由于它是不可复制的,因此需要有一种方法将其传递给事物,因此移动操作可以解决这个问题。