unique_ptr 的移动构造函数的实现问题

Problems with implementation of unique_ptr's move constructor

我正在尝试编写 unique_ptr 实现。我正在努力编写移动构造函数。这是我的问题:

  1. 当我将移动构造函数标记为 default 时,我的资源被删除了两次,当我移动分配指针时(下面的 auto foo2 = std::move(foo);)- 为什么?
  2. 当我尝试像这样 *rhs = nullptr 那样在移动构造函数中分配底层指针时(参见下面的实现),编译器说 *rhs 是一个右值,我不能将任何东西分配给它。
  3. 终于,rhs.m_ptr = nullptr 成功了。为什么它有效,而 *rhs = nullptr 无效?

我的代码:

#include <iostream>

namespace my
{
template <class T>
class unique_ptr
{
public:
    unique_ptr()
    {
        m_ptr = new T;
    }
    unique_ptr(const unique_ptr&) = delete;
    // move constructor
    unique_ptr(unique_ptr&& rhs)  // = default deletes m_ptr twice
    {
        m_ptr = *rhs;
        rhs.m_ptr = nullptr;  // *rhs = nullptr doesn't work (*rhs is an rvalue)
    }
    ~unique_ptr()
    {
        delete m_ptr;
    }
    T* operator->()
    {
        return m_ptr;
    }
    T* operator*()
    {
        return m_ptr;
    }
    unique_ptr& operator=(const unique_ptr&) = delete;
    // no move assignment yet
private:
    T* m_ptr;
};

}  // namespace my

struct Foo
{
    Foo()
    {
        std::cout << "Foo" << std::endl;
    }
    ~Foo()
    {
        std::cout << "~Foo" << std::endl;
    }
    void printHello()
    {
        std::cout << "Hello" << std::endl;
    }
};

int main()
{
    my::unique_ptr<Foo> foo;
    foo->printHello();

    auto foo2 = std::move(foo);

    return 0;
}

附带说明一下,显然我可以将不带任何模板参数的 unique_ptr 传递给 unique_ptr class 模板内的方法。编译器是否只是假设它是 T?

请丢弃与所述问题无关的任何其他实施错误。正在进行中。

1) 默认移动构造函数不知道您的 class 的语义。所以它移动了指针rhs,但它不会重置另一个指针,它也会在另一个析构函数中被删除。

2) *rhs调用operator*和return一个temporary/rvalueT*,内部指针的拷贝,和通常的不一致operator* 应该 return 一个 T& 或一个 const T&.

3) 请参阅 2。您正在 return 创建一个临时对象。

所以最后,你应该拥有:

unique_ptr(unique_ptr&& rhs)  // = default deletes m_ptr twice
: m_ptr(rhs.m_ptr)
{
    rhs.m_ptr = nullptr;  // *rhs = nullptr doesn't work (*rhs is an rvalue)
}

T& operator*() {return *m_ptr;}
const T& operator*() const {return *m_ptr;}

以此类推

你太努力了。您不必通过外部接口。只需赋值:

m_ptr = rhs.m_ptr;
rhs.m_ptr = nullptr;

此外,operator*()应该return一个T&,而不是T*