最近在书中看到关于智能指针的描述,由于之前没有使用过智能指针,便通过调试源代码(源代码的实现有点杂乱,并不能以最简单直观的方式呈现)了解原理后,以简单直接的方式写了一个shared_ptr指针类。

关于shared_ptr指针的几点介绍:
   1.共享指针在拷贝函数中拷贝已有的指针对象参数地址达到共享数据(简单的说就是一块类对象地址由多个指针同时指向并且使用);
   2.共享指针内部通过计数形式来记录共享调用类对象内存的次数(创建共享指针对象时计数为1,每被拷贝一次(赋值给别的新对象)计数加1),每释放一个共享指针对象计数减1,当指针计数为0时释放共享调用类对象内存;
   3.shared_ptr类共享指针内存及共享计数内存在没有通过手动释放的情况下,将会通过虚拟析构函数来做内存释放工作。

下面贴上代码:

template<typename _Tp>class new_allocator//采用了模板类特有的内存分配类,保证分配产生碎片变少的同时并且提高运行效率{public:typedef size_t     size_type;typedef ptrdiff_t  difference_type;typedef _Tp*       pointer;typedef const _Tp* const_pointer;typedef _Tp&       reference;typedef const _Tp& const_reference;typedef _Tp        value_type;template<typename _Tp1>struct rebind{ typedef new_allocator<_Tp1> other; };new_allocator() throw() { }new_allocator(const new_allocator&) throw() { }template<typename _Tp1>new_allocator(const new_allocator<_Tp1>&) throw() { }~new_allocator() throw() { }pointeraddress(reference __x) const { return &__x; }const_pointeraddress(const_reference __x) const { return &__x; }// NB: __n is permitted to be 0.  The C++ standard says nothing// about what the return value is when __n == 0.pointerallocate(size_type __n, const void* = 0){ /*if (__builtin_expect(__n > this->max_size(), false))__throw_bad_alloc();*/return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));}// __p is not permitted to be a null pointer.voiddeallocate(pointer __p, size_type){ ::operator delete(__p); }size_typemax_size() const throw() { return size_t(-1) / sizeof(_Tp); }// _GLIBCXX_RESOLVE_LIB_DEFECTS// 402. wrong new expression in [some_] allocator::constructvoid construct(pointer __p, const _Tp& __val) { ::new((void *)__p) _Tp(__val); }#ifdef __GXX_EXPERIMENTAL_CXX0X__template<typename... _Args>voidconstruct(pointer __p, _Args&&... __args){ ::new((void *)__p) _Tp(forward<_Args>(__args)...); }
#endifvoid destroy(pointer __p) { __p->~_Tp(); }};template<typename _Tp>class allocator: public new_allocator<_Tp>{public:typedef size_t     size_type;typedef ptrdiff_t  difference_type;typedef _Tp*       pointer;typedef const _Tp* const_pointer;typedef _Tp&       reference;typedef const _Tp& const_reference;typedef _Tp        value_type;template<typename _Tp1>struct rebind{ typedef allocator<_Tp1> other; };allocator() throw() { }allocator(const allocator& __a) throw(): __glibcxx_base_allocator<_Tp>(__a) { }template<typename _Tp1>allocator(const allocator<_Tp1>&) throw() { }~allocator() throw() { }// Inherit everything else.};class Ref_count_base/* 指针计数管理 */{public:Ref_count_base():m_ncount(0){}long GetCount()//获取当前计数{return m_ncount;}int ResetCount(int nAdd)//设置当前计数 1. 计数增加1 ,0. 计数减少1{if (1 == nAdd){++m_ncount;}else{--m_ncount;}return m_ncount;}private:long m_ncount;//计数变量};template <typename _Ty>class Point_Base/* 在这里做指针计数与数据对象的结合并且都是采用动态分配的方式(通过使用地址)达到数据共享  */{public:Point_Base(){ref_count = 0;}typedef _Ty* pointer;typedef _Ty& reference;protected:pointer m_obj;//共享类指针对象Ref_count_base* ref_count;//计数类指针对象};template <typename Pointer>
class Test_Pointer : public Point_Base<Pointer>//模板指针调用类
{typedef Test_Pointer<Pointer> test_pointer;typedef Pointer* pointer;typedef Pointer& reference;typedef allocator<Pointer> alloc_type;
public:virtual ~Test_Pointer()//每次类退出前会执行一次析构函数{if (!ref_count)/* 已经释放的情况下直接返回 */{return ;}int ncount = ref_count->ResetCount(0);if (0 == ncount && 0 != m_obj)//如果计数为0而且共享类指针还没有释放,那么这个共享指针没被共享和计数指针一起释放掉{m_alloc.deallocate(m_obj,sizeof(Pointer) * m_nSize); delete ref_count;}}Test_Pointer():m_nCritical(0),m_nCriticalRun(1),m_nSize(1)//无参数构造函数 分配一个共享类内存{if (0 == ref_count){ref_count = new Ref_count_base;}ref_count->ResetCount(1);m_obj = m_alloc.allocate(1);}template<class _Ux>explicit Test_Pointer(_Ux *_Px):m_nCritical(0),m_nCriticalRun(1)//有参数构造函数 根据输入的数量进行分配内存{if (0 == ref_count){ref_count = new Ref_count_base;}ref_count->ResetCount(1);m_obj = m_alloc.allocate(*_Px);m_nSize = *_Px;}pointer operator->() /* 增加临时临界区,在多个线程中保证智能指针数据同步,关于调用类对象的数据需要在线程中增加真正的临界区来同步化 */{if (1 == m_nCriticalRun){int nRun = m_nCritical;++m_nCritical;while (nRun != 0 && nRun != m_nCritical);--m_nCritical;}return m_obj;}Test_Pointer(test_pointer& _Other)//复制构造函数{*this = _Other;ref_count->ResetCount(1);}void SetCritical(int nRun);//调用共享类成员数据保护临界区 1. 启动 0. 不启动 默认1(在多线程情况下可以看出效果)void Reset();template<class _Ux>void Reset(_Ux *_Px)//把共享计数减一后 ,分配新的共享类内存{if (ref_count && 0 < ref_count->GetCount() && 0 != m_obj){ref_count->ResetCount(0);if (0 == ref_count->GetCount())/* 如果在共享指针计数减一为0的情况(属于没有在别的地方被使用) ,释放共享指针 和共享指针计数 */{m_alloc.deallocate(m_obj,sizeof(Pointer) * m_nSize); delete ref_count;}}ref_count = new Ref_count_base;ref_count->ResetCount(1);m_obj = m_alloc.allocate(*_Px);m_nSize = *_Px;}
private:    alloc_type m_alloc;//内存分配volatile int m_nCritical;//临界区volatile int m_nCriticalRun;//临界区是否运行int m_nSize;//共享类对象内存大小(个数)
};
template <typename Pointer>
inline void Test_Pointer<Pointer>::SetCritical(int nRun)
{m_nCriticalRun = nRun;
}
template <typename Pointer>
inline void Test_Pointer<Pointer>::Reset()/* 调用无参数Reset 把共享指针计数减一 并且把共享指针计数与共享指针赋值为0 */
{if (ref_count && 0 < ref_count->GetCount() && 0 != m_obj){ref_count->ResetCount(0);if (0 == ref_count->GetCount())/* 如果在共享指针计数减一为0的情况(属于没有在别的地方被使用) ,释放共享指针 和共享指针计数 */{m_alloc.deallocate(m_obj,sizeof(Pointer) * m_nSize); delete ref_count;}m_obj = 0;ref_count = 0;/* 因为已经脱离了上一个共享指针,所以共享指针 和共享指针计数都指向空 */m_nSize = 0;}
}

使用方法:

Test_Pointer<int> testint(new int(2));Test_Pointer<int> testint1 = testint;Test_Pointer<int> testint2 = testint1;Test_Pointer<int> testint3 = testint;//指向到此处可以看到4个类对象共享类指针地址与共享计数相同testint.Reset();//共享计数减一 并且共享类指针地址与共享计数地址赋值为0testint1.Reset(new int(4));//共享计数减一 并且共享类指针地址与共享计数地址赋值为0 , 然后分配新的共享类指针内存 与 共享计数testint1.SetCritical(0);

模板共享指针(shared_ptr)原理实现相关推荐

  1. 【Smart_Point】C/C++ 中共享指针 shared_ptr

    1. 共享指针 shared_ptr 目录 1. 共享指针 shared_ptr 1.1 共享指针解决的问题? 1.2 创建 shared_ptr 对象 1.3 分离关联的原始指针 1.4 自定义删除 ...

  2. C++:共享指针shared_ptr的理解与应用

    一 为什么要使用shared_ptr? 在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃.程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的.比如: 有 ...

  3. 智能指针shared_ptr的原理、用法和注意事项

    智能指针shared_ptr的原理.用法和注意事项 1 前言 2 shared_ptr原理 3 shared_ptr的基本用法 3.1 初始化 3.2 获取原始指针 4 智能指针和动态数组 4.1 c ...

  4. c++11中智能指针的原理,使用,实现

    文章目录 理解智能指针的原理 智能指针的使用 shared_ptr的使用 unique_ptr的使用 weak_ptr的使用 循环引用 指针指针的设计和实现: 理解智能指针的原理 c++程序设计中使用 ...

  5. C++中智能指针的原理、使用、实现

    C++中智能指针的原理.使用.实现 转自:https://www.cnblogs.com/wxquare/p/4759020.html 1 智能指针的作用 C++程序设计中使用堆内存是非常频繁的操作, ...

  6. C++(19)——智能指针shared_ptr

    shared_ptr的概念 shared_ptr实现共享式拥有(shared ownership)概念.多个智能指针可以指向相同对象,该对象和其相关资源会在"最后一个引用(reference ...

  7. C++智能指针: shared_ptr 实现详解

    文章目录 shared_ptr描述 声明 作用 原理实现 函数使用 关于shared_ptr循环引用问题 shared_ptr描述 声明 shared_ptr属于C++11特性中新加的一种智能指针,它 ...

  8. Boost智能指针——shared_ptr

    boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思义,boost::shared_ptr是可以 ...

  9. 智能指针shared_ptr、unique_ptr、weak_ptr

    智能指针 智能指针解决的问题 智能指针分类 shared_ptr 内存模型图 shared_ptr示例 shared_ptr含义 shared_ptr基本用法及常用函数 常用函数 智能指针的构造,初始 ...

最新文章

  1. 在Unity中制作4种不同的游戏
  2. html照片4张 9张布局,css实现朋友圈照片排列布局
  3. python【力扣LeetCode算法题库】面试题 10.01-合并排序的数组
  4. 讲故事的用户故事样例之1
  5. IBASE category 01 component hierarchy
  6. 后续升级鸿蒙系统,荣耀部分机型后续将支持升级为鸿蒙系统
  7. iOS - Swift NSData 数据
  8. luogu P3244 [HNOI2015]落忆枫音
  9. idea ssm打war包_IDEA下从零开始搭建SpringBoot工程
  10. Qt工作笔记-Qt creator如何生成dll,以及如何移植到vs上
  11. 汇编语言:汇编程序的hello world程序(实验9根据材料编程)
  12. VS2010编译器经常遇到的小问题
  13. 无线路由器建立usb共享打印服务器,无线路由器USB网络共享管理设置方法
  14. 硬件设计14---什么是预加重与去加重技术?
  15. 计算机考研各省份学校,想考研究生,哪个省份的高校更容易考上?
  16. 【电脑一点通】如何新建和切换Windows桌面
  17. webservice wsdl 转java对象
  18. 电源系统该如何选择电容大小及数量
  19. 欧几里得定理(nyoj775)
  20. pythonSSL证书 cookie session

热门文章

  1. 不小心执行了 rm -rf,除了跑路还有其他办法吗?
  2. 阿里云+HCT双证认证,架构师年薪达不到25.6万全额退款
  3. Ueditor结合七牛云及百度云存储(JAVA版,ueditor-1.4.3)实现图片文件上传
  4. Linux文件系统管理命令(第二版)
  5. 简述Spring技术内幕
  6. Gradle 2.3 发布
  7. Java数据结构与算法(26) - ch12堆(堆实现)
  8. SJTU OJ 3046 足球 题解
  9. OJ1038: 绝对值最大
  10. 逐步解析:杨辉三角(C语言)