Как удалить наложение оператора назначения из смарт-указателя .get()?

#c #c 11 #implementation

Вопрос:

Я внедряю интеллектуальный указатель, имитирующий std::shared_ptr

Я сделал большинство реализаций его функций. например) Нет оператора присваивания из необработанного указателя. перегрузка оператора bool…

Однако, в деталях, shared_ptr позволяет нам использовать его следующим образом.

—Редактировать

 1) shared_ptr<A> pA(new A);  // ok (Let it be Explicit)
2) shared_ptr<A> pA = new A; // no
3) shared_ptr<A> pA = nullptr; // ok (overload with nullptr_t)
4) shared_ptr<A> pA = make_shared<A>(); // usual use
   shared_ptr<A> pA2 = pA.get(); // no
 

Похоже .get() возвращает std::remove_extent_t* в библиотеке STL.
Чтобы реализовать такие детали, как я могу разработать свои функции SharedPtr?

Вот мой код SharedPtr, который может помочь понять мой вопрос. (Отредактировано)

 #pragma once
#include "CriticalSection.h"

template<typename T>
class SharedPtr
{
    template<typename S>
    friend class SharedPtr;
private:
    T*            m_pRes;
    UINT*         m_iRefCount;
    static CriticalSection m_tMutex;

public:
    T* operator->()
    {
        assert(m_pRes amp;amp; "[SharedPtr] Access Null Obj");
        return m_pRes;
    }
    const T* operator->() const
    {
        assert(m_pRes amp;amp; "[SharedPtr] Access Null Obj");
        return m_pRes;
    }

    T* Get() { return m_pRes; }
    const T* Get() const { return m_pRes; }
    T** GetAddressOf() { return amp;m_pRes; }
    T* const* GetAddressOf() const { return amp;m_pRes; }

    UINT UseCount() const 
    { 
        if (m_iRefCount == nullptr)
            return 0;
        return (*m_iRefCount); 
    }

    void Reset(T* _ptr = nullptr)
    {
        assert(_ptr != m_pRes);

        if (m_pRes)
        {
            SubRef();
        }
        
        m_pRes = _ptr;

        if (m_pRes)
        {
            assert(m_iRefCount == nullptr);
            m_iRefCount = new UINT(1);
        }
    }

    template<typename S>
    SharedPtr<S> CastTo() const
    {
        assert(m_pRes != nullptr amp;amp; dynamic_cast<S*>(m_pRes) != nullptr);

        SharedPtr<S> pCast;
        pCast.m_iRefCount = m_iRefCount;
        pCast.m_pRes = (S*)m_pRes;
        pCast.AddRef();

        return pCast;
    }

    constexpr operator bool() const { return m_pRes != nullptr; }
    bool operator==(nullptr_t) const { return m_pRes == nullptr; }
    bool operator!=(nullptr_t) const { return m_pRes != nullptr; }
    bool operator==(const SharedPtr<T>amp; rhs) const { return m_pRes == rhs.m_pRes; }
    bool operator!=(const SharedPtr<T>amp; rhs) const { return m_pRes != rhs.m_pRes; }

private:
    void AddRef()
    {
        m_tMutex.Lock();
          (*m_iRefCount);
        m_tMutex.UnLock();
    }
    void SubRef()
    {
        m_tMutex.Lock();
        --(*m_iRefCount);

        if ((*m_iRefCount) == 0)
        {
            SAFE_DELETE(m_iRefCount);
            SAFE_DELETE(m_pRes);
        }

        m_tMutex.UnLock();
    }
public:
    constexpr SharedPtr() noexcept
        :
        m_pRes(nullptr),
        m_iRefCount(nullptr)
    {}
    constexpr SharedPtr(nullptr_t) noexcept
        :
        m_pRes(nullptr),
        m_iRefCount(nullptr)
    {}
    explicit SharedPtr(T* _ptr)
        :
        m_pRes(_ptr),
        m_iRefCount(nullptr)
    {
        if (m_pRes)
        {
            m_iRefCount = new UINT(1);
        }
    }
    ~SharedPtr()
    {
        if (m_pRes)
        {
            SubRef();
        }
    }
    SharedPtramp; operator=(nullptr_t)
    {
        if (m_pRes)
        {
            SubRef();
        }

        m_pRes = nullptr;
        m_iRefCount = nullptr;
        return *this;
    }
    SharedPtr(const SharedPtr<T>amp; rhs)
        :
        m_pRes(rhs.m_pRes),
        m_iRefCount(rhs.m_iRefCount)
    {
        if (m_pRes)
        {
            AddRef();
        }
    }
    SharedPtramp; operator=(const SharedPtr<T>amp; _ptr)
    {
        if (m_pRes)
        {
            SubRef();
        }

        m_pRes = _ptr.m_pRes;
        m_iRefCount = _ptr.m_iRefCount;

        if (m_pRes)
        {
            AddRef();
        }

        return *this;
    }
    SharedPtr(SharedPtr<T>amp;amp; rhs) noexcept
        :
        m_pRes(rhs.m_pRes),
        m_iRefCount(rhs.m_iRefCount)
    {
        rhs.m_pRes = nullptr;
        rhs.m_iRefCount = nullptr;
    }
    SharedPtramp; operator=(SharedPtr<T>amp;amp; _ptr) noexcept
    {
        if (m_pRes)
        {
            SubRef();
        }

        m_pRes = _ptr.m_pRes;
        m_iRefCount = _ptr.m_iRefCount;

        _ptr.m_iRefCount = nullptr;
        _ptr.m_pRes = nullptr;

        return *this;
    }
};

template<typename T>
CriticalSection SharedPtr<T>::m_tMutex = {};
 

Комментарии:

1.Ваш пример для (2) не компилируется и не должен компилироваться, так как shared_ptr(Y* p) конструктор explicit

2. shared_ptr<A> pA = new A; не компилируется. shared_ptr<A> pA2 = pA.get(); не компилируется по той же самой причине. Точно shared_ptr<A> pA2(pA.get()); так же компилируется, по той же причине shared_ptr<A> pA(new A); компилируется. Вы пытаетесь приписать ему какие — то магические свойства shared_ptr::get -он ими не обладает.

3. Спасибо !, я неправильно понял shared_ptr в перегрузке. Изучил реализацию STL shared_ptr и благодарен за ваше объяснение;

4. Вы неправильно используете критический раздел.

5. Блокировка(), разблокировка() используют EnterCriticalSection и LeaveCriticalSection в качестве функции-члена класса. Не могли бы вы дать мне какие-нибудь предложения?