unique_ptr在多继承层次使用时,如果使用不当,容易出现
B* p = new D(); delete p;的问题
因此这里提出一个UniquePtr旨在正确处理析构。当然你需要付出一点小小的性能代价
包含文件
#include <memory>
template<typename T>
struct DeleteFuncs
{
static void deleteFunc(void* obj) { delete (T*)obj; }
};
struct UniqueDeleter
{
void(*m_deleter)(void*) = [](void*){};
UniqueDeleter(void(*func)(void*)) : m_deleter(func){}
void operator()(void* ptr){ m_deleter(ptr); }
};
template<class _Ty, class... _Types> inline
typename std::enable_if<!_STD is_array<_Ty>::value,
_STD unique_ptr<_Ty, UniqueDeleter> >::type MakeUnique(_Types&&... _Args)
{
return (_STD unique_ptr<_Ty, UniqueDeleter>(new _Ty(_STD forward<_Types>(_Args)...), DeleteFuncs<_Ty>::deleteFunc));
}
template<typename T>
using UniquePtr = typename std::unique_ptr<T, UniqueDeleter>;
测试代码
struct B
{
~B()
{
printf("~B()\n");
}
};
struct D : B
{
~D()
{
printf("~D()\n");
}
};
void deleteB(void* b)
{
printf("deleteB\n");
delete (B*)b;
}
void deleteD(void* d)
{
printf("deleteD\n");
delete (D*)d;
}
void test()
{
puts("");
{
UniquePtr<D> ptrD = MakeUnique<D>();
UniquePtr<B> ptrB = std::move(ptrD);
}
puts("");
{
UniquePtr<B> ptrB{ new D, deleteD };
}
puts("");
{
UniquePtr<B> ptrB{ new B, deleteB };
}
puts("");
{
UniquePtr<B> ptrB{ new D, deleteD };
UniquePtr<D> ptrD = { (D*)ptrB.release(), ptrB.get_deleter() };
}
puts("");
{
UniquePtr<B> ptrB{ new D, deleteD };
UniquePtr<D> ptrD = std::move((UniquePtr<D>&) ptrB);
}
puts("");
{
UniquePtr<B> ptrB{ new D, deleteD };
UniquePtr<D> ptrD = (UniquePtr<D>&&) ptrB;
}
puts("");
}