代码之家  ›  专栏  ›  技术社区  ›  user6646922

唯一指针移动构造函数的实现问题

  •  2
  • user6646922  · 技术社区  · 6 年前

    我正在尝试编写一个独特的\ptr实现。我正在努力写一个移动构造器。以下是我的问题:

    1. 当我将移动构造函数标记为 default ,我的资源被删除两次,当我移动时,分配一个指针( auto foo2 = std::move(foo); 下面)为什么?
    2. 当我试图在move构造函数中这样分配底层指针时 *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;
    }
    

    另一方面,显然,我可以在不使用任何模板参数的情况下将唯一的指针传递给唯一指针类模板内的方法。编译器只是假设它不是?

    请放弃与所描述的问题无关的任何其他实现错误。这是正在进行的工作。

    2 回复  |  直到 6 年前
        1
  •  6
  •   Matthieu Brucher    6 年前

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

    2) *rhs 电话 operator* 并返回一个临时/r值 T* ,内部指针的副本,与通常的不一致 操作员* 应该返回 T& 或A const T& .

    3)见2。您正在返回一个临时对象。

    最后,你应该拥有:

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

    等等。

        2
  •  2
  •   Pete Becker    6 年前

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

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

    此外, operator*() 应该归还 T& 不是 T* .