C++智能指针之Scoped_Ptr与SharePtr以及仿函数

Scoped_Ptr(防拷贝)

上一篇博客中已经讲述了智能指针之AutoPtr,它存在很大的缺陷.所以有一种更粗暴的方法——Scoped_Ptr.
Auto_Ptr出现的问题都是由于进行拷贝构造和赋值运算符重载引起的资源不能得到有效的释放.那么就直接不要进行拷贝构造和赋值运算符重载,那么就不会引起那些问题了.
下面是简单的代码实现:

  1 #pragma once                                                                                                           
  2 
  3 template<class T>
  4 class Scoped_Ptr
  5 {
  6 public:
  7     Scoped_Ptr(T* _ptr)
  8         :ptr(_ptr)
  9     {}
 10     ~Scoped_Ptr()
 11     {
 12         if(ptr)
 13         {
 14             delete ptr;
 15         }
 16     }
 17     T& operator*()
 18     {
 19         return *ptr;
 20     }
 21     T* operator->()
 22     {
 23         return ptr;
 24     }
 25 private:
 26     Scoped_Ptr(Scoped_Ptr<T>& _ptr);  //声明为私有,就不会有资源释放不当的问题产生.
 27     Scoped_Ptr<T>& operator=(Scoped_Ptr<T>& _ptr);
 28 protected:
 29     T* ptr;
 30 };

防拷贝的实现方法:
1.只声明不实现.
2.声明为私有.

SharePtr

就是使用引用计数的方法弥补智能指针的问题.
代码实现如下:

  1 #pragma once                                                                                                           
  2 #include <stdio.h>
  3 
  4 //声明,否则找不到
  5 template<class T>
  6 class Weak_Ptr;
  7 
  8 template<class T>
  9 class Share_Ptr
 10 {
 11     friend class Weak_Ptr<T>;
 12 public:
 13     Share_Ptr(T* _ptr)
 14         :ptr(_ptr)
 15          ,count(new int(1))
 16     {}
 17     ~Share_Ptr()
 18     {
 19         if(--(*count) == 0)
 20         {
 21             delete count;
 22             if(ptr)
 23             {
 24                 delete ptr;
 25                 printf("~Share_Ptr()\n"); //可以显示是否已经释放
 26             }
 27         }
 28     }
 29     T& operator*()
 30     {
 31         return *ptr;
 32     }
 33     T* operator->()
 34     {
 35         return ptr;
 36     }
 37     Share_Ptr(Share_Ptr<T>& s)
 38         :ptr(s.ptr)
 39          ,count(s.count)                                                                                               
 40     {
 41         ++(*count);
 42     }
 43     Share_Ptr<T>& operator=(Share_Ptr<T>& s)
 44     {
 45         //if(this != &s)
 46         if(ptr != s.ptr)  
 47         {
 48             if(--(*count) == 0)
 49             {
 50                 delete ptr;
 51                 delete count;
 52             }
 53             ptr = s.ptr;
 54             count = s.count;
 55             ++(*count);
 56         }
 57         return *this;
 58     }
 59 protected:
 60     T* ptr;
 61     int* count;
 62 };
 63 
 64 template<class T>
 65 class Weak_Ptr
 66 {
 67     public:
 68         Weak_Ptr(const Share_Ptr<T>& s)
 69             :ptr(s.ptr)
 70         {}
 71         T& operator*()
 72         {
 73             return *ptr;
 74         }
 75         T* operator->()
 76         {
 77             return ptr;
 78         }
 79     private:                                                                                                           
 80         T* ptr;
 81 };
 82 
 83 //struct ListNode
 84 //{
 85 //    Share_Ptr<ListNode> prev;
 86 //    Share_Ptr<ListNode> next;
 87 //    int data;
 88 //
 89 //    ListNode()
 90 //        :prev(NULL)
 91 //        ,next(NULL)
 92 //    {}
 93 //};
 94 struct ListNode
 95 {
 96     Weak_Ptr<ListNode> prev;
 97     Weak_Ptr<ListNode> next;
 98     int data;
 99 
100     ListNode()
101         :prev(NULL)
102         ,next(NULL)
103         ,data(int())
104     {}                                                                                                                 
105 };
106 
107 void TestCycle()
108 {
109     //ListNode* n1 = new ListNode;
110     //ListNdoe* n2 = new ListNode;
111     //可能存在异常引起执行流乱跳不能正常释放资源
112     //delete n1;
113     //delete n2;
114     
115     //使用智能指针,但是存在循环引用的问题
116     Share_Ptr<ListNode> n1(new ListNode); 
117     Share_Ptr<ListNode> n2(new ListNode);
118     n1->next = n2;
119     n2->prev = n1;
120     
121     //解决智能指针的循环引用的问题,增加一个weak_ptr弱指针去辅助智能指针,
122     //只要在循环引用中不增加引用计数就可以避免这样的问题.
123     
124 }          

存在问题如下图所示:
这里写图片描述

存在问题:循环引用.
解决:引入Weak_Ptr即让其引用计数不加加就好.

总结:
Auto_Ptr:存在问题:可能会引起资源不能及时释放.
解决1:管理权转移法.(仍然存在问题,所以不建议使用)
解决2:Scoped_Ptr防拷贝智能指针,防止拷贝构造和赋值运算符的重载.
解决3:Share_Ptr引用计数法,需要配合Weak_Ptr的使用,防止产生循环引用的问题.
问题2:由于new的可能是一个单独的对象,也可能是一组对象.解决这个问题可以有两种方法:
解决1:再写一个类去实现数组的delete[];
解决2:通过仿函数来直接通过对象来模拟函数去正确的释放资源.

仿函数

通过重载(),就可以用对象名来调用(),像函数一样实现某些功能.
例如:

  1 #include <iostream>
  2 
  3 using namespace std;
  4 
  5 struct Compare
  6 {
  7     bool operator()(int x,int y)
  8     {
  9         return x>y;
 10     }
 11 };
 12 int main()
 13 {
 14     Compare compare;
 15     cout<<compare(3,2)<<endl;                                                                                          
 16     return 0;
 17 }

仿函数呢,还可以在调用标准库的SORT算法时进行传参,因为排序可以从小到大也可以从大到小,在传参时第二个参数就可以通过仿函数来实现.
对于上面的Share_Ptr智能指针,由于如果是new了数组,我们也可以通过仿函数来得到有效的释放资源.具体做法如下:

  1 #include <iostream>                                                                                                    
  2 
  3 using namespace std;
  4 
  5 template<class T>
  6 struct deleteArr
  7 {
  8     void operator()(T* ptr)
  9     { 
 10         delete[] ptr;
 11     } 
 12 };

^~^

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值