zoukankan      html  css  js  c++  java
  • 智能指针之 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 [yejy@yejy cmake-00]$ ./smartptr 
    2 construct..
    3 RefCount: 3
    4 welcome Test..
    5 welcome Test..
    6 ptr is exit 
    7 destruct..
    8 [yejy@yejy 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机制

  • 相关阅读:
    封装
    面向对象的思想
    Arrays工具类
    二分查找
    选择排序
    冒泡排序
    对象数组
    二维数组
    一维数组
    循环语句注意事项
  • 原文地址:https://www.cnblogs.com/blog-yejy/p/9030722.html
Copyright © 2011-2022 走看看