zoukankan      html  css  js  c++  java
  • 数据结构库——智能指针的实现(下)

    1,SmartPointer 被设计成每次只允许一个智能指针对象指向一片堆空间,也就限制了智能指针的运用,不能够运用于LinkList;

      

    2,本节完成 SharedPointer 的具体实现:

     

    3,SharedPointer 设计要点:

           1,类模板:

                  1,通过计数机制(ref)标识堆空间;

                         1,堆内存被指向时:ref++;

                         2,指针被置空时:ref--;

                         3,ref == 0 时:释放堆内存;          

    4,计数机制原理剖析:

          

           1,计数变量和堆空间对象生命周期完全一样,且都在堆空间中声明的;

          

    5,SharedPointer 类的声明:

           

          

    6,智能指针比较:

           1,由于 SharedPointer 支持多个对象同时指向一片堆空间,因此必须支持比较操作;

    7,SharedPointer 智能指针的实现:

      1 #ifndef SHAREDPOINTER_H
      2 #define SHAREDPOINTER_H
      3 
      4 #include "Pointer.h"
      5 #include <cstdlib>
      6 #include "Exception.h"
      7 
      8 namespace DTLib
      9 {
     10 
     11 template <typename T>
     12 class SharedPointer : public Pointer<T>
     13 {
     14 protected:
     15    int* m_ref;  // 指向堆空间的计数变量,和对象相关联且同生命周期;
     16 
     17     void assign(const SharedPointer<T>& obj)
     18     {
     19         this->m_ref = obj.m_ref;
     20         this->m_pointer = obj.m_pointer;
     21 
     22         if( this->m_ref )  // obj 也可能为空;
     23         {
     24             (*this->m_ref)++;  
     25         }
     26    }
     27 
     28 public:
     29    SharedPointer(T* p = NULL) : m_ref(NULL)  // 用初始化列表来初始化成员变量;调用时用堆空间指针来初始化参数 p
     30     {
     31         if( p )
     32         {
     33             this->m_ref = static_cast<int*>(std::malloc(sizeof(int)));  // 申请堆空间给计数指针指向
     34 
     35             if( this->m_ref )
     36             {
     37                 this->m_pointer = p;
     38 
     39                 *(this->m_ref) = 1;  // 这里不能为 *(this->m_ref)++;,因为里面是随机值,而如果重新申请,则必然首先为 1,++只是为了后来的拷贝赋值而准备的;
     40             }
     41             else
     42             {
     43                 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to creat SharedPointer object ...");
     44             }
     45         }
     46    }
     47 
     48     SharedPointer(const SharedPointer<T>& obj) : Pointer<T>(NULL)  // 初始化赋值调用,这里为了消除警告所以显示调用父类构造函数
     49     {
     50         assign(obj);
     51    }
     52 
     53    SharedPointer<T>& operator= (const SharedPointer<T>& obj)// 由于 SharedPointer 支持多个对象同时指向一片堆空间,因此必须支持比较操作;
     54    {
     55         if( this != &obj)
     56         {
     57             clear();  // 当前指针可能指向了别的对象,所以赋值前先让其不再指向别的对象,先清空,这样避免指向的别的对象的内存泄漏;
     58             assign(obj);
     59         }
     60 
     61         return *this;
     62    }
     63 
     64     void clear()  // 将当前指针置为空;
     65     {
     66         int* ref = this->m_ref;
     67         T* toDel = this->m_pointer;
     68         this->m_ref = NULL;
     69         this->m_pointer = NULL;
     70 
     71         if( ref )
     72         {
     73             (*ref)--;  // 不再指向的时候,要处理对象的计数;
     74 
     75             if( *ref == 0 )
     76             {
     77                 free(ref);  // 释放计数变量指向的空间;
     78                 delete toDel;  // 释放堆空间;
     79             }
     80         }
     81    }
     82 
     83     ~SharedPointer()
     84     {
     85         clear();
     86     }
     87 };
     88 
     89 /* 通过全局函数的方式来重载相等操作符 */
     90 template <typename T>
     91 bool operator== (const SharedPointer<T>& l, const SharedPointer<T>& r)
     92 {
     93     return (l.get() == r.get());  // 指向的堆空间是一个则相等;
     94 }
     95 
     96 /* 通过全局函数的方式来重载不等操作符 */
     97 template <typename T>
     98 bool operator!= (const SharedPointer<T>& l, const SharedPointer<T>& r)
     99 {
    100     return !(l == r); // 不相等操作符重载使用相等操作符来实现;
    101 }
    102 
    103 }
    104 
    105 #endif // SHAREDPOINTER_H

    8,SharedPointer 的测试代码:

     1 #include <iostream>
     2 #include "SharedPointer.h"
     3 
     4 using namespace std;
     5 using namespace DTLib;
     6 
     7 class Test : public Object
     8 {
     9 public:
    10    int value;
    11 
    12     Test() : value(0)
    13     {
    14         cout << "Test()" << endl;
    15    }
    16 
    17     ~Test()
    18     {
    19         cout << "~Test()" << endl;
    20     }
    21 };
    22 
    23 int main()
    24 {
    25     SharedPointer<Test> sp0(new Test());
    26     SharedPointer<Test> sp1 = sp0;
    27    SharedPointer<Test> sp2 = NULL;
    28 
    29     sp2 = sp1;
    30    sp2->value = 100;
    31 
    32     cout << sp0->value << endl;
    33     cout << sp1->value << endl;
    34     cout << sp2->value << endl;
    35    cout << (sp0 == sp1) << endl;
    36 
    37    sp2.clear();
    38 
    39     cout << (sp0 == sp2) << endl;
    40     const SharedPointer<Test> sp3 = new Test();
    41    sp3->value = 100;
    42 
    43     return 0;
    44 }

    9,智能指针使用军规:

           1,智能用来指向堆空间中的单个变量(对象);

           2,不同类型的智能指针对象不能混合使用;

           3,不要使用 delete 释放智能指针指向的堆空间;

          

    10,小结:

           1,SharedPointer 最大程度的模拟了原生指针的行为;

           2,计数机制确保多个智能指针合法的指向同一片堆空间;

      3,智能指针只能用于指向堆空间中的内存;

           4,不同类型的智能指针不要混合使用;

           5,堆对象的生命周期由智能指针进行管理;

  • 相关阅读:
    图的存储代码实现
    最小生成树算法
    图的遍历
    图的存储结构
    ftp服务器的配置
    利用c++利用odbc连接mysql数据库
    测试odbc连接sqlsever数据库是否成功的代码
    gk888t打印机安装
    Win10下windows mobile设备中心连接不上的方法无法启动
    js千分位加逗号和四舍五入保留两位小数
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10922689.html
Copyright © 2011-2022 走看看