zoukankan      html  css  js  c++  java
  • 再谈智能指针

    http://www.cnblogs.com/lewiskyo/p/4214592.html  之前写过一篇文章介绍智能指针,并且简单实现了auto_ptr.

    里面提到 auto_ptr 不能做为Stl容器的元素,原因具体是 http://www.360doc.com/content/14/0429/16/1317564_373230218.shtml

    简要来说就是在对Stl容器元素进行复制构造时,不能改变原来的值(const T2& value),而auto_ptr在复制构造的时候,一定会修改元素的值(即将指向实际内存地址的指针置NULL),否则就会两个指针指向同一个地址,当析构的时候就会出现重复析构。

    所以是赋值函数出了问题。

    但如果仅使用构造函数,则是没问题的,如这里的例子 http://www.cnblogs.com/lewiskyo/p/4604839.html

    而在引入shared_ptr后,这些问题都解决了,因为shared_ptr增加了引用数量这个变量。

    这里想简单实现下 shared_ptr, 代码基于 http://www.cnblogs.com/yangshaoning/archive/2012/03/18/cpp_smart_pointer.html 

    这里加上了模板,代码如下:

      1 #include <iostream>
      2 #include <vector>
      3 using namespace std;
      4 
      5 
      6 template <typename T> class SmartPtr;
      7 
      8 template<typename T>
      9 class RefPtr
     10 {
     11     friend class SmartPtr<T>;
     12 
     13     RefPtr(T *pointer = NULL):t( pointer), count(1)
     14     {
     15     }
     16 
     17     ~RefPtr()
     18     {
     19         cout << "destructor delete refptr" <<endl;
     20         delete t;
     21     }
     22 
     23     T *t;
     24     int count;
     25 
     26 };
     27 
     28 
     29 template<typename T>
     30 class SmartPtr
     31 {
     32     public:
     33 
     34         // 为了兼容stl预分配空间使用默认构造函数
     35         SmartPtr()
     36         {
     37             rp = NULL;
     38         }
     39 
     40         SmartPtr( T* object): rp(new RefPtr<T>(object))
     41         {
     42         }
     43 
     44         SmartPtr(const SmartPtr& rhs)
     45         {
     46             // 为了兼容stl预分配空间使用默认构造函数时,rp = NULL
     47             if ( rhs.rp != NULL)
     48             {
     49                 rp = rhs.rp;
     50                 ++rp->count;
     51             }
     52         }
     53 
     54         SmartPtr& operator=(const SmartPtr &rhs)
     55         {
     56             if(this == &rhs)
     57                 return *this;
     58             
     59             if (rp)
     60             {
     61                 --rp->count;
     62                 if (rp->count == 0)
     63                     delete rp;
     64             }
     65             
     66             
     67             rp = rhs.rp;
     68             ++rp->count;
     69     
     70             return *this;
     71         }
     72 
     73         ~SmartPtr()
     74         {
     75             if (rp)
     76             {
     77                 --rp->count;
     78                 if (rp->count == 0)
     79                     delete rp;                
     80             }
     81 
     82         }
     83 
     84     private:
     85         RefPtr<T> *rp;
     86 };
     87 
     88 
     89 int main()
     90 {
     91     
     92     {
     93         SmartPtr<int> s1(new int(10));
     94         SmartPtr<int> s2(s1);
     95     
     96         SmartPtr<int> s3 (new int (20));
     97         s3 = s1;
     98     }
     99 
    100     cout << "operator v1" << endl;
    101 
    102     {
    103         vector<SmartPtr<int> > v1;
    104         v1.push_back(SmartPtr<int>(new int (10)));
    105         v1.push_back(SmartPtr<int>(new int (10)));
    106         v1.push_back(SmartPtr<int>(new int (10)));
    107         v1.push_back(SmartPtr<int>(new int (10)));
    108     }
    109 
    110     cout << "operator v1 end" << endl;
    111 
    112     cout << "operator v2" << endl;
    113 
    114     {
    115         vector<SmartPtr<int> > v2(10);
    116         v2[0] = SmartPtr<int>(new int (10));
    117         v2[1] = SmartPtr<int>(new int (20));
    118         v2[2] = SmartPtr<int>(new int (30));
    119         v2[3] = SmartPtr<int>(new int (40));
    120     }
    121 
    122     cout << "operator v2 end" << endl;
    123 }

    这里不管是Stl的构造函数,还是赋值函数都没问题了。

    几个注意点:

    1. 第六行需要前置声明SmartPtr,否则RefPtr会识别不了这个友元.

    2. RefPtr::count仅在SmartPtr内改变值,所有指向同一个对象的SmartPtr操作同一个count。

    3. SmartPtr::rp仅是一个指针,若然多个SmartPtr指向同一个对象,那么多个SmartPtr::rp则共享同一份地址,当SmartPtr析构时,--count,count==0时要 delete rp, 释放rp指向的地址,其他情况不必delete,只需要让系统回收rp指针所占用的地址即可。

    后话:

      拿别人代码改造实现过程中有几个基础知识点值得在这里提一下的,也是提醒自己。

      1.  代码114行, vector<SmartPtr<int> >v2(10). 这里是常见的给vector预分配空间的做法,实际上是 调用10次 SmartPtr<int>() 默认构造函数得到10个实例放到容器里面。  代码116到119行, 执行SmartPtr的赋值函数,但此时 this->rp依然为NULL,所以不能执行 --count操作,要对指针是否为NULL进行判断。 当然这些操作都是为了能让智能指针加入Stl中作为元素使用而设定的。

      2.  vector.push_back(object). 实际上是调用类的复制构造函数。

    Coding Life
  • 相关阅读:
    04-修改域控的操作主机(主备切换)
    03-域控上删除组织单位的错误
    02-搭建域控的从节点
    01-域控服务器的搭建
    06-"Login failed for user 'NT AUTHORITYSYSTEM'. 原因: 无法打开明确指定的数据库。[客户端:<local machine>]"异常处理
    04-数据库范式
    9-系统交互式登录无需按Ctrl+Alt+Del的策略启用
    05-拒绝了对对象'server'的VIEW SERVER STATE权限
    37-SQLServer的审核/审计功能介绍
    微信小程序 设置计时器(setInterval)、清除计时器(clearInterval)
  • 原文地址:https://www.cnblogs.com/lewiskyo/p/6241195.html
Copyright © 2011-2022 走看看