智能指针之 shared_ptr

   std::shared_ptr 是通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可占有同一对象大概实现了一下,主要实现原理为,共享指针内部持有堆资源的指针以及引用计数的指针,通过对这两个指针的维护,达到多个共享对象对同一资源的控制

  实现主要分为三个文件。share_ptr.h,smart_ptr_define.h, main.cpp  (编译平台:Linux centos 7.0 编译器:gcc 4.8.5 )

 1 //smart_ptr_define.h
 2 #ifndef __SMART_PTR_DEFINE_H__
 3 #define __SMART_PTR_DEFINE_H__
 4
 5 #include <assert.h>
 6
 7 #define PTR_ASSERT(x) assert(x)
 8
 9 #define _SMART_PTR_BEGIN    namespace smartptr {
10 #define _SMART_PTR_END        }
11 #define _SMART_PTR    ::smartptr::
12
13 #endif

  主要实现文件share_ptr.h

  1 #ifndef __SHARE_PTR_H__
  2 #define __SHARE_PTR_H__
  3
  4 #include <iostream>
  5 #include "smart_ptr_define.h"
  6
  7 _SMART_PTR_BEGIN
  8
  9 template <class T>
 10 struct default_deleter
 11 {
 12     void operator()(T* ptr)
 13     {
 14         if (ptr != NULL)
 15         {
 16             delete ptr;
 17             ptr = NULL;
 18         }
 19     }
 20 };
 21
 22 template <class T, class deleter = default_deleter<T> >
 23 class shared_ptr
 24 {
 25 public:
 26     typedef shared_ptr<T, deleter> SHARE_PTR;
 27
 28     shared_ptr()
 29     {
 30         m_ptr = NULL;
 31         m_iRefCount = NULL;
 32     }
 33
 34     explicit shared_ptr(T* ptr)
 35     {
 36         if (ptr != NULL)
 37         {
 38             m_ptr = ptr;
 39             RefCountInit();
 40         }
 41     }
 42
 43     shared_ptr(deleter d, T* ptr)
 44     {
 45         if (ptr != NULL)
 46         {
 47             m_ptr = ptr;
 48             m_deleter = d;
 49             RefCountInit();
 50         }
 51     }
 52
 53     //拷贝构造
 54     shared_ptr(const SHARE_PTR& sh_ptr)
 55     {
 56         if (sh_ptr.m_ptr != NULL)
 57         {
 58             m_ptr = sh_ptr.m_ptr;
 59             m_deleter = sh_ptr.m_deleter;
 60             m_iRefCount = sh_ptr.m_iRefCount;
 61
 62             RefCountIncrease();
 63         }
 64     }
 65
 66     //赋值运算符
 67     SHARE_PTR& operator = (const SHARE_PTR& sh_ptr)
 68     {
 69         if (this != &sh_ptr)
 70         {
 71             RefCountDecrease();
 72
 73             if (sh_ptr.m_ptr != NULL)
 74             {
 75                 m_ptr = sh_ptr.m_ptr;
 76                 m_deleter = sh_ptr.m_deleter;
 77                 m_iRefCount = sh_ptr.m_iRefCount;
 78
 79                 RefCountIncrease();
 80             }
 81         }
 82
 83         return (*this);
 84     }
 85
 86     ~shared_ptr()
 87     {
 88         RefCountDecrease();
 89     }
 90
 91 public:
 92     //提领操作
 93     T& operator*()
 94     {
 95         PTR_ASSERT(m_ptr != NULL);
 96         return *(m_ptr);
 97     }
 98
 99     //原始指针操作
100     T* operator->()
101     {
102         PTR_ASSERT(m_ptr != NULL);
103         return m_ptr;
104     }
105
106     operator bool() const
107     {
108         return m_ptr != NULL;
109     }
110
111     //取得原始指针
112     T* getPointer()
113     {
114         PTR_ASSERT(m_ptr != NULL);
115         return m_ptr;
116     }
117
118     //获得引用计数
119     int getRefCount()
120     {
121         PTR_ASSERT(m_iRefCount != NULL);
122         return *m_iRefCount;
123     }
124
125
126 private:
127     void RefCountInit()
128     {
129         m_iRefCount = new int(1);
130     }
131
132     void RefCountIncrease()
133     {
134         if (m_iRefCount != NULL)
135         {
136             ++(*m_iRefCount);
137         }
138     }
139
140     void RefCountDecrease()
141     {
142         if (m_iRefCount != NULL && --(*m_iRefCount) == 0)
143         {
144             m_deleter(m_ptr);
145             delete m_iRefCount;
146             m_ptr = NULL;
147             m_iRefCount = NULL;
148         }
149     }
150
151 private:
152     int* m_iRefCount; //引用计数
153
154     T*  m_ptr; //对象指针
155
156     deleter m_deleter; //删除器
157 };
158
159 _SMART_PTR_END
160 #endif // !__SHARE_PTR_H__

  main函数测试

 1 #include "share_ptr.h"
 2 #include <memory>
 3
 4 class Test
 5 {
 6 public:
 7     Test()
 8     {
 9         std::cout << "construct.." << std::endl;
10     }
11
12     void method()
13     {
14         std::cout << "welcome Test.." << std::endl;
15     }
16
17     ~Test()
18     {
19         std::cout << "destruct.." << std::endl;
20     }
21 };
22
23 int main()
24 {
25     Test* t1 = new Test();
26
27     _SMART_PTR shared_ptr<Test> shptr(t1);
28
29     _SMART_PTR shared_ptr<Test> shptr1(shptr);
30
31     _SMART_PTR shared_ptr<Test> shptr2 = shptr1;
32
33     std::cout << "RefCount: " << shptr2.getRefCount() << std::endl;
34
35     shptr2->method();
36
37     (*shptr2).method();
38
39     if (shptr2)
40     {
41         std::cout << "ptr is exit " << std::endl;
42     }
43
44
45
46     return 0;
47 }

  测试最后打印:

1 [[email protected] cmake-00]$ ./smartptr
2 construct..
3 RefCount: 3
4 welcome Test..
5 welcome Test..
6 ptr is exit
7 destruct..
8 [[email protected] cmake-00]$

  shared_ptr主要需实现的功能点如下(以下总结引用自网络,非原创):

  1. 没有参数构造的时候,初始化为空,即对象和引用计数的两个指针都为0
  2. 使用指针为参数构造时,拥有此指针,在没有智能指针指向它时进行析构
  3. 智能指针复制时,两个智能指针共同拥有内部指针,引用计数同时+1
  4. 智能指针可以使用智能指针或普通指针重新赋值。重载=操作符,对于智能指针赋值,需要考虑是否自赋值,以避免将自身析构了后再重新赋值,而普通指针赋值给智能指针,则不需要考虑自赋值,因为两者本身是两个类型
  5. 获得底层指针的访问,定义getPtrPointer()getPtrCounter()来分别返回底层指针和引用计数,定义operator bool()来处理智能指针隐式转换为bool的情况
  6. 重载->×操作符 ,来实现与普通指针相同的指针访问
  7. 需要支持隐式指针类型转换,static_cast不支持而dynamic_cast支持的转换则使用Cast<T2>()成员函数来解决。考虑定义友元类,以防止指向派生类的智能指针有权限访问基类的内部对象;当转型不成功时,返回为空 (未实现)
  8. 如果一个裸指针直接用来创建两个智能指针的话,期望的情况是当两个智能指针析构掉的时候,该指针会被delete两次从而崩溃(这是shared_ptr的特点)
  9. 不处理循环引用(也是shared_ptr的特点),可以通过与weak_ptr协作来打破循环
  10. 实现deleter机制

原文地址:https://www.cnblogs.com/blog-yejy/p/9030722.html

时间: 2024-10-12 20:27:16

智能指针之 shared_ptr的相关文章

boost智能指针之shared_ptr和weak_ptr

std::auto_ptr很多的时候并不能满足我们的要求,比如auto_ptr不能用作STL容器的元素.boost的smart_ptr中提供了4种智能指针和2种智能指针数组来作为std::auto_ptr的补充. shared_ptr<boost/shared_ptr.hpp>:使用shared_ptr进行对象的生存期自动管理,使得分享资源所有权变得有效且安全. weak_ptr<boost/weak_ptr.hpp>:weak_ptr 是 shared_ptr 的观察员.它不会干

【STL学习】智能指针之shared_ptr

前面已经学习过auto_ptr,这里补充另外一种智能指针,比auto_ptr要更强力更通用的shared_ptr. shared_ptr 简介及使用选择  几乎所有的程序都需要某种形式的引用计数智能指针,这种指针让我们不再需要为两个对象或更多对象共享的对象的生命周期而编写复杂的逻辑(写起来有点绕口),当被共享的对象引用计数降为0时,被共享对象被自动析构. 引用计数指针分为插入式(instrusive)和非插入式(non-instrusive)两种.前者要求它所管理的类提供明确的函数或数据成员用于

智能指针tr1::shared_ptr、boost::shared_ptr使用

对于tr1::shared_ptr在安装vs同时会自带安装,但是版本较低的不存在.而boost作为tr1的实现品,包含 "Algorithms Broken Compiler Workarounds Concurrent Programming Containers Correctness and Testing Data Structures Domain Specific Function Objects and Higher-order Programming Generic Progra

详解Boost库智能指针(shared_ptr &amp;&amp; scoped_ptr &amp;&amp; weak_ptr )

我们先来解释一下什么叫智能指针? 智能指针是利用RAII(在对象的构造函数中执行资源的获取(指针的初始化),在析构函数中释放(delete 指针):这种技法把它称之为RAII(Resource Acquisition Is Initialization:资源获取即初始化))来管理资源. 其本质思想是:将堆对象的生存期用栈对象(智能指针)来管理.也就是当new一个堆对象的时候,立刻用智能指针来接管,具体做法是在构造函数中进行初始化(用一个指针指向堆对象),在析构函数调用delete来释放堆对象.由

C++ 智能指针(shared_ptr/weak_ptr)源码分析

C++11目前已经引入了unique_ptr, shared_ptr, weak_ptr等智能指针以及相关的模板类enable_shared_from_this等.shared_ptr实现了C++中的RAII机制,它不仅仅具有一般指针(build-in/raw)的特性,更重要的是它可以自动管理用户在堆上创建的对象的生命周期,让用户不用负责内存回收,避免内存泄漏.一般的智能指针都定义为一个模板类,它的类型由被管理的对象类型初始化,内部包含了指向该对象的指针以及指向辅助生命周期管理的管理对象的指针.

C++ 11智能指针之shared_ptr

 shared_ptr是一个引用计数智能指针,用于共享对象的所有权.它可以从一个裸指针.另一个shared_ptr.一个auto_ptr.或者一个weak_ptr构造.还可以传递第二个参数给shared_ptr的构造函数,它被称为删除器(deleter).删除器用于处理共享资源的释放,这对于管理那些不是用new分配也不是用delete释放的资源时非常有用.shared_ptr被创建后,就可以像普通指针一样使用了,除了一点,它不能被显式地删除.shared_ptr的比较重要的接口如下: tem

智能指针(二):shared_ptr实现原理

前面讲到auto_ptr有个很大的缺陷就是所有权的转移,就是一个对象的内存块只能被一个智能指针对象所拥有.但我们有些时候希望共用那个内存块.于是C++ 11标准中有了shared_ptr这样的智能指针,顾名思义,有个shared表明共享嘛.所以shared_ptr类型的智能指针可以做为STL容器的元素 下面我们来瞧瞧shared_ptr具体是咋实现的.相较auto_ptr有下面几个不同的地方: 1.引进了一个计数器shared_count,用来表示当前有多少个智能指针对象共享指针指向的内存块 2

C++智能指针: auto_ptr, shared_ptr, unique_ptr, weak_ptr

本文参考C++智能指针简单剖析 内存泄露 我们知道一个对象(变量)的生命周期结束的时候, 会自动释放掉其占用的内存(例如局部变量在包含它的第一个括号结束的时候自动释放掉内存) int main () { { int a = 1; printf("%d\n", a); } { a = 2; printf("%d\n", a); } } 这样会编译错误. 但是如果这样写呢? void func(int &o) { int *p = new int(o); ret

关于智能指针类型shared_ptr的计数问题

一.关键 每个shared_ptr所指向的对象都有一个引用计数,它记录了有多少个shared_ptr指向自己 shared_ptr的析构函数:递减它所指向的对象的引用计数,如果引用计数变为0,就会销毁对象并释放相应的内存 引用计数的变化:决定权在shared_ptr,而与对象本身无关 二.引用计数初步 shared_ptr<int> sp; //空智能指针 shared_ptr<int> sp2 = make_shared<int>(3); shared_ptr<