前面提到可以用引用计数 + 写时拷贝 融合在一起, 为我们的智能指针增加新的功能
代码增加了CRefCount
类, 来专门对CStudent类的对象的使用情况做统计
类很简单, 构造的时候, 计数器赋值为1
析构的时候, 把它删掉
增加引用的时候会+1
当计数器减少为0的时候, 会释放掉
delete this;
这么写, 就一定要保证自己是一个堆对象
class CRefCount
{
friend class CSmartPtr;
CRefCount(CStudent* pStu)
{
m_pObj = pStu;
m_nCount = 1;
}
~CRefCount()
{
delete m_pObj;
m_pObj = NULL;
}
void AddRef()
{
m_nCount++;
}
void Release()
{
if (--m_nCount == 0)
{
// 这么写, 就一定要保证自己是一个堆对象
delete this;
}
}
private:
CStudent* m_pObj;
int m_nCount;
};
将这个类与前面的智能指针结合起来
智能指针类
class CSmartPtr
{
public:
CSmartPtr()
{
m_pRef = NULL; // 计数器, 然后跳到private看成员变量, 发现是指针
}
CSmartPtr(CStudent* pStu) // 外界传递进来一个对象, 显然也需要是一个堆对象, new出来
{
m_pRef = new CRefCount(pStu); // 构造很明显, 只能new
}
~CSmartPtr() // 对象需要析构, 析构的时候不能完全析构, 因为智能指针的析构需要决定智能指针内部的资源, 是否能够析构, 即: 看内部资源的引用计数起是否减为0
{
m_pRef->Release(); // 会进到引用计数器CRefCount类的Release函数, 对计数器进行判断, 引用计数器删掉的话, 会连带delete 原来所传进来的CStudent指针
}
CSmartPtr(CSmartPtr& obj) // 拷贝构造
{
// if (m_pRef != NULL)
// {
// m_pRef->Release();
// }
m_pRef = obj.m_pRef; // 右边的值赋值给左边
m_pRef->AddRef(); // 引用计数器 + 1
}
CSmartPtr& operator=(CSmartPtr& obj)
{
if (m_pRef == obj.m_pRef) // 本来就相等, 就直接返回
{ // 等号运算赋重载的时候, 讲道理应该右边的引用-1, 左边的+1, 但是如果右边=左边, 那么会造成 左边=空, 因为右边减少为0了, 直接来个特判, 能够避免这种情况的发生
return *this;
}
if (m_pRef != NULL)
{
m_pRef->Release();
}
m_pRef = obj.m_pRef;
m_pRef->AddRef();
return *this;
}
void test2()
{
cout << "test2" << endl;
}
CStudent* operator->()
{
return m_pRef->m_pObj;
}
CStudent** operator&()
{
return &m_pRef->m_pObj;
}
CStudent& operator*()
{
return *m_pRef->m_pObj;
}
operator CStudent*()
{
return m_pRef->m_pObj;
}
// operator CStudent()
// {
// return *m_pStu;
// }
private:
CRefCount* m_pRef;
};
总代码:
#include "stdafx.h"
#include <iostream.h>
//智能指针
class CStudent
{
public:
CStudent()
{
}
void test()
{
cout << "CStudent" << endl;
}
private:
char* m_pszBuf;
int m_nSex;
};
class CRefCount
{
friend class CSmartPtr;
CRefCount(CStudent* pStu)
{
m_pObj = pStu;
m_nCount = 1;
}
~CRefCount()
{
delete m_pObj;
m_pObj = NULL;
}
void AddRef()
{
m_nCount++;
}
void Release()
{
if (--m_nCount == 0)
{
delete this;
}
}
private:
CStudent* m_pObj;
int m_nCount;
};
class CSmartPtr
{
public:
CSmartPtr()
{
m_pRef = NULL;
}
CSmartPtr(CStudent* pStu)
{
m_pRef = new CRefCount(pStu);
}
~CSmartPtr()
{
m_pRef->Release();
}
CSmartPtr(CSmartPtr& obj)
{
// if (m_pRef != NULL)
// {
// m_pRef->Release();
// }
m_pRef = obj.m_pRef;
m_pRef->AddRef();
}
CSmartPtr& operator=(CSmartPtr& obj)
{
if (m_pRef == obj.m_pRef)
{
return *this;
}
if (m_pRef != NULL)
{
m_pRef->Release();
}
m_pRef = obj.m_pRef;
m_pRef->AddRef();
return *this;
}
void test2()
{
cout << "test2" << endl;
}
CStudent* operator->()
{
return m_pRef->m_pObj;
}
CStudent** operator&()
{
return &m_pRef->m_pObj;
}
CStudent& operator*()
{
return *m_pRef->m_pObj;
}
operator CStudent*()
{
return m_pRef->m_pObj;
}
// operator CStudent()
// {
// return *m_pStu;
// }
private:
CRefCount* m_pRef;
};
int main(int argc, char* argv[])
{
CSmartPtr obj = new CStudent;
CSmartPtr obj4 = new CStudent;
CSmartPtr obj2 = obj;
{
CSmartPtr obj3;
obj3 = obj;
obj3 = obj4;
}
//CStudent* pStu = new CStudent;
//obj.test();
//pStu ==> obj->
//pStu->test();
//obj->->test();
//pStu->test();
// obj->test(); //==> pStu->test();
//
// CStudent** ppStu = &obj;
//
// //(obj).test();
// (*obj).test();
//
// CSmartPtr obj2 = obj;
//
// obj2->test();
return 0;
}
存在致命问题
但是现在还存在一个致命问题, CSmartPtr中表示的类型是固定的, 是CStudent. 以后的资源可能是各种类型, 文件指针啊, 奇奇怪怪的指针啊, 因此需要添加一个模板
将上述总代码中 所有CrefCount类中的CStudent改成T
注意, CRefCount类中用到了CSmartPtr类, 需要在CRef类前面先声明CSmartPtr类的存在
template<typename T>
class CSmartPtr;
template<typename T>
class CRefCount
{
friend class CSmartPtr<T>;
public:
CRefCount(T* pStu)
{
m_pObj = pStu;
m_nCount = 1;
}
~CRefCount()
{
delete m_pObj;
m_pObj = NULL;
}
void AddRef()
{
m_nCount++;
}
void Release()
{
if (--m_nCount == 0)
{
delete this;
}
}
private:
T* m_pObj;
int m_nCount;
};
CSmartPtr类前面也要改成模板
template<typename T>
class CSmartPtr
{
public:
CSmartPtr()
{
m_pRef = NULL;
}
CSmartPtr(T* pStu)
{
m_pRef = new CRefCount(pStu);
}
~CSmartPtr()
{
m_pRef->Release();
}
CSmartPtr(CSmartPtr& obj)
{
// if (m_pRef != NULL)
// {
// m_pRef->Release();
// }
m_pRef = obj.m_pRef;
m_pRef->AddRef();
}
CSmartPtr& operator=(CSmartPtr& obj)
{
if (m_pRef == obj.m_pRef)
{
return *this;
}
if (m_pRef != NULL)
{
m_pRef->Release();
}
m_pRef = obj.m_pRef;
m_pRef->AddRef();
return *this;
}
void test2()
{
cout << "test2" << endl;
}
T* operator->()
{
return m_pRef->m_pObj;
}
T** operator&()
{
return &m_pRef->m_pObj;
}
T& operator*()
{
return *m_pRef->m_pObj;
}
operator T*()
{
return m_pRef->m_pObj;
}
// operator CStudent()
// {
// return *m_pStu;
// }
private:
CRefCount<T>* m_pRef;
};
总代码:
#include <iostream>
using namespace std;
//智能指针
class CStudent
{
public:
CStudent()
{
}
void test()
{
cout << "CStudent" << endl;
}
private:
char* m_pszBuf;
int m_nSex;
};
template<typename T>
class CSmartPtr;
template<typename T>
class CRefCount
{
friend class CSmartPtr<T>;
public:
CRefCount(T* pStu)
{
m_pObj = pStu;
m_nCount = 1;
}
~CRefCount()
{
delete m_pObj;
m_pObj = NULL;
}
void AddRef()
{
m_nCount++;
}
void Release()
{
if (--m_nCount == 0)
{
delete this;
}
}
private:
T* m_pObj;
int m_nCount;
};
template<typename T>
class CSmartPtr
{
public:
CSmartPtr()
{
m_pRef = NULL;
}
CSmartPtr(T* pStu)
{
m_pRef = new CRefCount<T>(pStu);
}
~CSmartPtr()
{
m_pRef->Release();
}
CSmartPtr(CSmartPtr& obj)
{
// if (m_pRef != NULL)
// {
// m_pRef->Release();
// }
m_pRef = obj.m_pRef;
m_pRef->AddRef();
}
CSmartPtr& operator=(CSmartPtr& obj)
{
if (m_pRef == obj.m_pRef)
{
return *this;
}
if (m_pRef != NULL)
{
m_pRef->Release();
}
m_pRef = obj.m_pRef;
m_pRef->AddRef();
return *this;
}
void test2()
{
cout << "test2" << endl;
}
T* operator->()
{
return m_pRef->m_pObj;
}
T** operator&()
{
return &m_pRef->m_pObj;
}
T& operator*()
{
return *m_pRef->m_pObj;
}
operator T*()
{
return m_pRef->m_pObj;
}
// operator CStudent()
// {
// return *m_pStu;
// }
private:
CRefCount<T>* m_pRef;
};
int main(int argc, char* argv[])
{
CStudent* pStu = new CStudent();
// CRefCount<CStudent> ref(pStu);
CSmartPtr<CStudent> sp1(pStu);
CSmartPtr<CStudent> sp2(new CStudent());
//sp2 = sp1;
return 0;
}