shellmad-18_C++新特性 智能指针的简易实现及添加模板

前面提到可以用引用计数 + 写时拷贝 融合在一起, 为我们的智能指针增加新的功能

代码增加了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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值