2015-05-22 62 views
0

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

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

回访所有权:汽车独特=的std :: make_unique () –

+1

不支持移动语义,你不能把它的向量 – sp2danny

回答

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 

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

+0

如果我理解你的权利它需要支持非标准的移动操作库std:move()并没有其他优点? – maniac

+0

@maniac你必须明白移动语义是什么意思。它允许你“窃取”右侧的资源,并且在处理复制对象的“昂贵”时非常有用。在某些情况下,您想防止复制(例如'unique_ptr'),所以移动是唯一的选择。是的,在这种情况下,您需要移动构造函数和移动赋值运算符,否则将无法传递您的对象。注意:'std :: move'只对右值执行转换,不会移动任何东西。 – vsoftco

0

std::unique_ptr需要移动构造函数和移动赋值运算符,因为它是不可复制的因此唯一的对象。由于它是不可复制的,因此需要将它传递给事物,并由此将操作转移到此处。

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