智能指针,可以简化资源的管理,从根本上消除资源(包括内存)泄漏的可能性。其实,智能指针本质上并不神秘,其实就是 RAII 资源管理功能的自然展现而已,下面提供一种实现。
/*******************************************************
文 件: CSmartPoint.h
描 述: 智能指针类,多线程安全
修 改:
********************************************************/
#pragma once
#include <atomic>
namespace Base
{
namespace detail
{
//swap 函数实现参考
template<class T>
void swap(T &t1, T &t2)
{
T temp = std::move(t1);
t1 = std::move(t2);
t2 = std::move(temp);
}
}
class CSharedCount {
public:
CSharedCount()
{
_count.store(1, std::memory_order_relaxed);
}
void AddCount()
{
_count.fetch_add(1, std::memory_order_relaxed);
}
long ReduceCount()
{
return _count.fetch_sub(1, std::memory_order_relaxed);
}
long GetCount() const
{
return _count.load(std::memory_order_relaxed);
}
private:
std::atomic_long _count;
};
template <typename CType>
class CSmartPoint
{
public:
CSmartPoint(CType *ptr = nullptr)
:_ptr(ptr)
{
if (_ptr)
{
_shared_cnt = new CSharedCount;
}
}
~CSmartPoint()
{
if (_ptr && !_shared_cnt->ReduceCount())
{
delete _ptr;
delete _shared_cnt;
}
}
/*========================auto_ptr实现 Begin========================
CSmartPoint& operator=(CSmartPoint& rhs)
{
std::swap(_ptr, rhs.ptr_);
return *_ptr;
}
CSmartPoint(CSmartPoint& tOther)
{
_ptr = tOther.release();
}
========================auto_ptr实现 End========================*/
/*========================unique_ptr实现 Begin========================
CSmartPoint& operator=(const CSmartPoint& rhs) = delete;
CSmartPoint(const CSmartPoint& tOther) = delete;
CSmartPoint& operator=(CSmartPoint rhs)
{
std::swap(_ptr, rhs.ptr_);
return *_ptr;
}
CSmartPoint(CSmartPoint&& tOther)
{
_ptr = tOther.release();
}
//支持派生类向基类转换
template <typename U>
CSmartPoint(CSmartPoint<U>&& tOther)
{
_ptr = tOther.release();
}
CType* Release()
{
CType* ptr = _ptr;
_ptr = nullptr;
return ptr;
}
========================unique_ptr实现 End========================*/
/*
对象不存在,且没用别的对象来初始化,就是调用了构造函数;
对象不存在,且用别的对象来初始化,就是拷贝构造函数(上面说了三种用它的情况!)
对象存在,用别的对象来给它赋值,就是赋值函数。
*/
//拷贝构造函数调用时机:
//eg1、 Type a; Type b(a);
//eg2、Type a; Type b = a;
CSmartPoint(const CSmartPoint& tOther)
{
_ptr = tOther._ptr;
if (_ptr)
{
tOther._shared_cnt->AddCount();
_shared_cnt = tOther._shared_cnt;
}
}
//赋值函数调用时机:将已经分配内存的对象赋值
//eg1、Type a; Type b; b = a;
CSmartPoint& operator=(CSmartPoint rhs)
{
rhs.Swap(*this);
return *this;
}
//移动构造函数应当从另一个对象获取资源,清空其资源,并将其置为一个可析构的状态
//移动构造函数:1、解决临时对象的多次拷贝开销 2、支持move语义
CSmartPoint(CSmartPoint&& tOther)
{
_ptr = tOther._ptr;
if (_ptr)
{
_shared_cnt = tOther._shared_cnt;
tOther._ptr = nullptr;
}
}
//支持派生类向基类转换
template <typename U>
friend class CSmartPoint;
template <typename U>
CSmartPoint(CSmartPoint<U>&& tOther)
{
_ptr = tOther._ptr;
if (_ptr)
{
tOther._shared_cnt->AddCount();
_shared_cnt = tOther._shared_cnt;
}
}
template <typename U>
CSmartPoint(const CSmartPoint<U>& other, CType* ptr)
{
_ptr = ptr;
if (_ptr)
{
other._shared_cnt->AddCount();
_shared_cnt = other._shared_cnt;
}
}
//返回了保存变量的裸指针,因此,如果裸指针是一个类变量,可以继续调用类的成员函数,因此智能指针的使用看起来和裸指针一样的效果
//比如:CSmartPoint<Type> pVar; pVar->func(); 等同于 (pVar.operator->())->func();
CType* operator->()const{ return _ptr; }
//返回了保存变量的引用,实现和裸指针一样的解引用效果
//比如:CSmartPoint<Type> pVar; (*pVar).func();等同于 (pVar.operator*())->func();
CType& operator*()const{ return *_ptr; }
//实现和裸指针一样的判空效果
//比如:CSmartPoint<Type> pVar; if(!pVar);等同于 if(!(pVar.operator bool()))
operator bool()const{ return _ptr; }
CType* Get(){ return _ptr; }
void Swap(CSmartPoint& rhs)
{
std::swap(_ptr, rhs._ptr);
std::swap(_shared_cnt, rhs._shared_cnt);
}
private:
CType* _ptr{nullptr};
CSharedCount* _shared_cnt{nullptr};
};
template <typename Type>
void swap(CSmartPoint<Type>& lhs, CSmartPoint<Type>& rhs)
{
lhs.swap(rhs);
}
/** @struct template<typename T, typename U>
* CSmartPoint<T> dynamic_point_cast(const CSmartPoint<U>& other)
* @brief 具有类似裸指针的dynamic_cast转换
*
* 用法
* CSmartPoint<X> ptr3 = dynamic_point_cast<CSmartPoint<X> >(ptr2);
*/
template<typename T, typename U>
CSmartPoint<T> dynamic_point_cast(const CSmartPoint<U>& other)
{
T* ptr = dynamic_cast<T*>(other.Get());
return CSmartPoint<T>(other, ptr);
}
template<typename T, typename U>
CSmartPoint<T> const_pointer_cast(const CSmartPoint<U>& other)
{
T* ptr = const_cast<T*>(other.Get());
return CSmartPoint<T>(other, ptr);
}
template<typename T, typename U>
CSmartPoint<T> reinterpret_pointer_cast(const CSmartPoint<U>& other)
{
T* ptr = reinterpret_cast<T*>(other.Get());
return CSmartPoint<T>(other, ptr);
}
template<typename T, typename U>
CSmartPoint<T> static_pointer_cast(const CSmartPoint<U>& other)
{
T* ptr = static_cast<T*>(other.Get());
return CSmartPoint<T>(other, ptr);
}
}