参考:shared_ptr实现,auto_ptr-实现
注1:std::shared_ptr带引用计数
注2:std::auto_ptr不带引用计数(但支持release方法,断开指向)
参考:http://blog.csdn.net/lollipop_jin/article/details/8499530
(Owed by: 春夜喜雨http://blog.csdn.net/chunyexiyu)
智能指针通常使用如下
std::shared_ptr <CDemo> ipDemo = new CDemo;
通常提供
.get() method获取裸指针
operator ->同CDemo->使用效果一致
智能指针使用的过程中,不需要对ipDemo进行手动的释放,如果非要手动释放,也不能采用通常的方式
delete ipDeom.get() (错误) ---会引发重复释放的崩溃,原因是手动释放掉了,智能指针也会释放一次。
可以使用
ipDemo = nullptr;
ipDeom.reset(nullptr)来进行手动释放,或者是什么都不做,等待智能指针自动释放
智能指针实现的原理是
存储引用计数
同时共享引用计数内存地址
(注意shared_ptr是用引用计数的,auto_ptr是无引用计数的)
实现这个有两种方法:
一种引用计数放入到智能指针类中,通过new实现,智能指针存储new出的地址
一种引用计数放入到类中
第一种:
智能指针需要实现:(参考如下代码)
引用计数,在合适的时机删除指针 (申请内存,从而进行计数共享)
Copy构造 (定义时:= new时,或是等于另一个时)
operator = (定义后,再赋值情况)
operator -> (使用->时的情况处理)
.get()方法 (返回裸指针)
当前自己写的一个指针指针的实现参考下面的代码段。
第二种:
需要类里面提供计数,指针类调用类里的计数
支持智能指针的类需要实现
计数变量
提供addRef/ReleaseRef/QueryRef方法
智能指针实现
构造、析构调用类的addRef/ReleaseRef/QueryRef,在合适的时机删除指针
Copy构造
operator =
operator ->
.get()
第一种的样例实现
#pragmaonce
template <classT> classCMySharedPtr { public: //构造时置为空 CMySharedPtr() :m_pRefCount(nullptr),m_pPointer(nullptr) {} //析构时,检查计数,释放内存 ~CMySharedPtr() { //释放原有 freeCurrentPointer(); } CMySharedPtr(T*pValue) { //构造 createNewPointer(pValue); }
CMySharedPtr(CMySharedPtr&ipValue) { // Copy构造 CopyAutPtr(ipValue); }
public: T*get() { returnm_pPointer; }
voidoperator =(T*pValue) { if (pValue == nullptr) { //置空-释放原有 freeCurrentPointer(); } else { //释放原有 freeCurrentPointer();
//申请新的 createNewPointer(pValue); } }
voidoperator = (CMySharedPtr&ipValue) { //引用计数地址相同:意味着指向同一地址 if (ipValue.m_pRefCount == m_pRefCount) { return; }
//释放原有 freeCurrentPointer();
//申请新的 CopyAutPtr(ipValue); }
//重载->符号 T*operator ->() { return (get()); }
protected: //通过一个指针构造另一个 voidCopyAutPtr(CMySharedPtr&ipValue) { //计数加一 m_pRefCount =ipValue.m_pRefCount; //指针有效时加一 if (m_pRefCount != nullptr) (*m_pRefCount)++; //指针指向 m_pPointer =ipValue.m_pPointer; }
//申请新指针 template <classT> voidcreateNewPointer(T*pValue) { m_pRefCount =newint(); *m_pRefCount = 1; m_pPointer =pValue; }
//释放原有指针 voidfreeCurrentPointer() { //存在时进行释放 if (m_pPointer != nullptr &&m_pRefCount !=nullptr) { if (*m_pRefCount > 1) { (*m_pRefCount)--; } elseif (*m_pRefCount == 1) { *m_pRefCount = 0; deletem_pPointer; deletem_pRefCount; } }
//置初值 m_pPointer =nullptr; m_pRefCount =nullptr; }
private: int*m_pRefCount; T*m_pPointer; };
|
智能指针使用时,直接使用即可,不用关心它的释放。
classDemo { public: Demo() { printf(("Demo Create\n")); } ~Demo() { printf(("Demo Delete\n")); } public: voidShow() { printf(("Call Demo Show\n")); } }; voidTestCode() { CMySharedPtr<Demo>ipValue =newDemo(); //构造 ipValue->Show(); // 调用operator->
CMySharedPtr<Demo>ipValue2 =ipValue; // copy构造 ipValue2 =ipValue; // 调用operator = ipValue->Show(); } |
第一种实现,智能指针中存储引用计数,能支持所有的类型
第二种显现,类中存储引用计数,智能指针只能支持实现计数的类
第一种实现,不支持:(无论是使用auto_ptr还是shared_ptr,都永远不要写这样的代码)
Deom* pa = new A; |
会导致重复释放。
第二种实现,支持上面那种,因为计数存储在类中,上面的代码,会让计数=2,不会产生重复释放的问题。
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)