博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【C++】智能指针shared_ptr 定位删除器(仿函数)
阅读量:4031 次
发布时间:2019-05-24

本文共 2259 字,大约阅读时间需要 7 分钟。

智能指针shared_ptr 用引用计数实现看起来不错,但却存在问题。

1、引用计数更新存在着线程安全;

2、循环引用--使用一个弱引用智能指针(weak_ptr)来打破循环引用(weak_ptr不增加引用计数)

3、定置删除器和空间分配器

比如打开一个文件的关闭,用malloc开辟出来的空间,用引用计数实现会出现问题。

对改变引用计数时加锁可以解决引用计数更新存在着线程安全

循环引用问题

#include
using namespace std;#include
//库中包含shared_ptrstruct ListNode{ shared_ptr
 _prev; shared_ptr
 _next; ~ListNode() { cout << "~ListNode()" << endl; }};void  Test2(){ shared_ptr
 cur(new ListNode);//1 shared_ptr
 next(new ListNode);//2 cout << "cur->" << cur.use_count() << endl;//use_count返回shared_ptr的引用计数 cout << "next->" << next.use_count() << endl; cur->_next = next;//3 next->_prev = cur;//4 cout << "cur->" << cur.use_count() << endl; cout << "next->" << next.use_count() << endl;}//经过语句1、2之后cur和next的引用计数为1,经过语句1、2后引用计数为2。//但是最后两个对象均不能释放,因为cur的要释放的前提是next释放,而next的释放又依赖于cur的释放,最后就形成了循环引用。//weak_ptr(弱引用智能指针)会对引用计数会做特殊处理解决这个问题。struct ListNode{    weak_ptr
 _prev;    weak_ptr
 _next;    ~ListNode()    {        cout << "~ListNode()" << endl;    }};

定置删除器和空间分配器(ps:空间分配器的定置特殊场景下才会这样使用)

如果指针是一个指向文件类型的,在析构函数中只需关闭文件即可,而不是释放空间;如果空间是通过malloc开辟出来的,那么在析构函数中要调用free函数,而不是delete操作符。上述问题通过仿函数就可以解决。具体代码如下:

template
class Del{public: void operator() (const T *ptr) { delete ptr; }};//仿函数实现FClose和Freestruct FClose{ void operator() (void* ptr) { cout << "Close" << endl; fclose((FILE*)ptr); }};struct Free{ void operator() (void* ptr) { cout << "Free" << endl; free(ptr); }};template
>class SharedPtr{public: SharedPtr(T* ptr) :_ptr(ptr) , _pCount(new long(1)) {} SharedPtr(T* ptr,Deleter del) :_ptr(ptr) , _pCount(new long(1)) , _del(del) {} SharedPtr
& operator=(SharedPtr
 sp) { swap(_ptr, sp._ptr); swap(_pCount, sp._pCount); return *this; } ~SharedPtr() { cout << "~SharedPtr()" << endl; Release(); } T& operator*() { return *_ptr; } T* GetPtr()//返回原指针_ptr { return  _ptr; } T* operator->() { return _ptr; } void Release()//释放内存 { if (--(*_pCount) == 0) { _del(_ptr); delete _pCount; } }private: T* _ptr; long* _pCount; Deleter _del;};void Test3(){ //定制删除器和分配器 SharedPtr
 sp(new int(6)); SharedPtr
 sp1(fopen("test.text", "w"), FClose()); SharedPtr
 sp2((int*)malloc(sizeof(int)* 6), Free());}

转载地址:http://kilbi.baihongyu.com/

你可能感兴趣的文章
Android下调用收发短信邮件等(转载)
查看>>
Android中电池信息(Battery information)的取得
查看>>
SVN客户端命令详解
查看>>
Android/Linux 内存监视
查看>>
Linux系统信息查看
查看>>
用find命令查找最近修改过的文件
查看>>
Android2.1消息应用(Messaging)源码学习笔记
查看>>
在android上运行native可执行程序
查看>>
Phone双模修改涉及文件列表
查看>>
android UI小知识点
查看>>
Android之TelephonyManager类的方法详解
查看>>
android raw读取超过1M文件的方法
查看>>
ubuntu下SVN服务器安装配置
查看>>
MPMoviePlayerViewController和MPMoviePlayerController的使用
查看>>
CocoaPods实践之制作篇
查看>>
[Mac]Mac 操作系统 常见技巧
查看>>
苹果Swift编程语言入门教程【中文版】
查看>>
捕鱼忍者(ninja fishing)之游戏指南+游戏攻略+游戏体验
查看>>
iphone开发基础之objective-c学习
查看>>
iphone开发之SDK研究(待续)
查看>>