#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 в качестве функции-члена класса. Не могли бы вы дать мне какие-нибудь предложения?