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

代码增加了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;
}

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

  1. C++11新特性——智能指针之unique_ptr

    此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记使用. unique_ptr独享它指向的对象,也就是说,同时只有一个unique_ptr指向同一个对象,当这个unique_ptr被销毁 ...

  2. C++11新特性——智能指针之shared_ptr

    此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记使用. 1.智能指针shared_ptr shared_ptr共享它指向的对象,多个shared_ptr可以指向(关联)相同的对象,在内 ...

  3. C++新特性探究(十八):智能指针

    一.智能指针及RAII 问题:   C++中最令人头疼的问题是强迫程序员对申请的资源(文件,内存等)进行管理,一不小心就会出现泄露(忘记对申请的资源进行释放)的问题. C++的解决办法:RAII    ...

  4. C++11 解决内存泄露问题的智能指针:shared_ptr、unique_ptr、weak_ptr

    我们经常听到内存泄漏,但是对这个抽象的概念一直没有什么理解,比如产生内存泄漏又将如何,我平时写程序从来不考虑这个等等.这篇的目的:第一,给大家实验实验内存泄露带来的问题,让大家直观感受内存泄露.第二, ...

  5. C++11新特性之智能指针

    智能指针的特性 智能指针可以自动释放不再使用的内存,能够有效的防止内存泄漏. 智能指针是一个对象,普通指针是一个变量. 智能指针是对普通指针的封装,其安全性要高于直接使用普通指针. 智能指针的分类 共 ...

  6. C++新特性探究(18.1):C++11 shared_ptr智能指针

      在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃.程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的.比如:   有些内存资源已经被释放,但指向它的 ...

  7. C++ 智能指针(unique_ptr / shared_ptr)代码实现

    文章目录 unique_ptr 智能指针的实现 shared_ptr 智能指针的实现 指针类型转换 unique_ptr 智能指针的实现 一个对象只能被单个unique_ptr 所拥有. #inclu ...

  8. Android智能指针

    智能指针的目标   在使用指针的时候容易出现的问题不外乎下面几个.首先,指针在使用之前都必须初始化,这个还算容易解决,在创建指针变量的时候同步初始化就好了:第二个问题就是经常忘记delete,就我的经 ...

  9. C++ 智能指针 :内存泄漏、 RAII、智能指针、auto_ptr、unique_ptr、shared_ptr、weak_ptr、定制删除器deleter

    文章目录 内存泄漏 什么是内存泄漏 内存泄漏的危害: 如何避免内存泄漏 RAII 智能指针 auto_ptr unique_ptr shared_ptr 循环引用问题 weak_ptr 定制删除器 内 ...

最新文章

  1. 使用脚本编写 Vim 编辑器,第 5 部分: 事件驱动的脚本编写和自动化
  2. 数据产品--浅析如何搭建维度指标系统
  3. php mysql 查询时间_PHP-MySQL查询需要大量时间才能执行
  4. 业界资讯:adobe 技术开发中心 放出游戏单元
  5. 学python最重要的是_Python学习,要选哪个版本?
  6. qt动画效果_Qt编写自定义控件44-天气仪表盘
  7. 叮咚买菜更新招股书:发行价区间为23.5-25.5美元
  8. watir-webdriver使用过程中异常
  9. Visual C# 2005 - 如何于DataGridView控件中以跨数据行方式显示数据
  10. 有哪些不怎么火,实际上却很厉害的软件
  11. 【SQL基础】SQL增删改查基本语句
  12. 弹性地基梁板实用计算_YJK软件前处理之计算参数的设置(上篇)
  13. 电信大型服务器机房_香港十大知名服务器机房汇总详细介绍
  14. 广东省计算机ps操作题,PS上机操作练习题
  15. 国家及地区MySQL数据
  16. 阿里云CentOS7挂载SSD云盘的方法
  17. WPF窗体自适应电脑分辨率的问题
  18. LintCode刷题(入门篇)
  19. 电商外包众生相:从淘宝吃饭到海外运营
  20. 华硕FA506IV重装系统以后驱动都打过官网的驱动,无线网还是不能用的解决办法。

热门文章

  1. Linux挂载命令mount 详解
  2. 微博消息分析-大数据项目
  3. 制作双足机器人用易拉罐_小小创客 | 用易拉罐做一台平衡车,跑起来太炫酷了吧...
  4. 抖音直播聊天窗口如何关闭,抖音直播间看不到弹幕
  5. OpenWrt配置打印服务器无线桥接,手机无线打印
  6. react中将json对象转换为数组
  7. 怎样取消红米k40pro拍照水印(教程分享)
  8. 如何快速理解IMU积分、预积分、误差、方差
  9. 计算机毕设(附源码)JAVA-SSM金牛社区疫情防控系统
  10. 基于51单片机红外测距仪阈值报警仪表设计