shared_ptr循环引用定置删除器
shared_ptr虽然方便,但是它有着一个致命的缺陷就是循环引用问题,因为shared_ptr本身并没有能力解决这个问题,所以我们又引入了弱指针weak_ptr来辅助shared_ptr解决这个问题。
那么循环引用又是什么场景?
举个栗子:
假设现在我们要创建一个双向×××链表,但是这个链表的指针域全部都用shared_ptr维护:
struct Node
{
int _data;
shared_ptr<Node> _next;
shared_ptr<Node> _prev;
}
假设现在先创建两个结点,并用shared_ptr维护这两个结点:
shared_ptr<Node> sp1(new Node);
shared_ptr<Node> sp2(new Node);
现在将这两个指针互相连接:
sp1->_next=sp2;
sp2->prev=sp1;
为了解决循化引用问题,我们又引入了weak_ptr弱指针,用来辅助shared_ptr。注意weak_ptr不能单独使用,必须辅助shared_ptr才能使用。weak_ptr是一种不控制所指向对象生存周期的智能指针,它指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一但最后一个指向对象的shared_ptr被销毁,对象就会被销毁,即使有weak_ptr指向对象,对象还是会被释放。
例:
所以为了解决上面栗子中的循环引用问题,我们可以将指针域的智能指针声明为弱指针。
struct Node
{
int _data;
weak_ptr<Node> _next;
weak_ptr<Node> _prev;
}
二、定置删除器
一般情况下,我们都用智能指针是用来管理动态内存的,其实智能指针是用来管理资源的,资源很多,动态内存只是资源的一种,比如说我们可以用智能指针来管理文件,那么我们就不能用智能指针默认的删除器了,因为要管理文件的话最后是fclose,而不是delete,所以我们就必须自己定制一个删除器。
例:以管理文件为例,实现定置删除器。
要实现定置删除器,就要用到仿函数:仿函数就是将"()"重载。
//定置删除器的仿函数
struct Fclose
{void operator()(void *ptr){fclose((FILE *)ptr);cout << "fclose()" << endl;}
};
void test()
{boost::shared_ptr<FILE> sp(fopen("test.txt","w"),Fclose()); //调用构造函数构造一个匿名对象传递过去,文件正常关闭
}再举一个栗子:
用智能指针管理malloc开辟的动态内存,那么我们在释放的时候就要用free释放:
//定置删除器的仿函数
struct Free
{void operator()(void *ptr){free(ptr);}
};
void test()
{boost::shared_ptr<int> sp((int *)malloc(sizeof(int)),Free()); //能够正确的释放空间
}
三、简单的实现一个有定置删除器的shared_ptr
struct Fclose
{void operator()(void *ptr){fclose((FILE *)ptr);cout << "fclose()" << endl;}
};struct Free
{void operator()(void *ptr){free(ptr);cout << "free()" <<endl;}
};//默认删除器是delete
struct DefaultDel
{void operator()(void* ptr){delete ptr;cout << "delete ptr" << endl;}
};template<typename T, typename D = DefaultDel>
class SharedPtr //采用引用计数,实现一个可以有多个指针指向同一块内存的类模板,SharedPtr是类模板,不是智能指针类型
{
public:SharedPtr(T* ptr, D del = DefaultDel());SharedPtr(const SharedPtr<T,D>& sp);SharedPtr<T,D>& operator=(SharedPtr<T,D> sp);T& operator*();T* operator->();~SharedPtr();int Count(){return *_pCount;}
private:void Release(){if (--(*_pCount) == 0){_del(_ptr);delete _pCount;_ptr = NULL;_pCount = NULL;}}
private:T* _ptr;int* _pCount;D _del;
};template<typename T, typename D = DefaultDel>
SharedPtr<T,D>::SharedPtr(T* ptr,D del)
:_ptr(ptr)
, _pCount(new int(1))
,_del(del){}template<typename T, typename D = DefaultDel>
SharedPtr<T,D>::SharedPtr(const SharedPtr<T,D>& sp)
{_ptr = sp._ptr;_pCount= sp._pCount;++(*_pCount);
}template<typename T, typename D = DefaultDel>
SharedPtr<T,D>& SharedPtr<T,D>::operator=(SharedPtr<T,D> sp)
{std::swap(sp._ptr,_ptr);std::swap(sp._pCount,_pCount);return *this;
}template<typename T, typename D = DefaultDel>
T& SharedPtr<T,D>::operator*()
{return *_ptr;
}template<typename T, typename D = DefaultDel>
T* SharedPtr<T,D>::operator->()
{return _ptr;
}template<typename T, typename D = DefaultDel>
SharedPtr<T,D>::~SharedPtr()
{Release();
}//测试用例
void test()
{SharedPtr<int> sp(new int(1));SharedPtr<FILE,Fclose> sp1(fopen("test.txt","w"),Fclose());SharedPtr<string,Free> sp3((string *)malloc(sizeof(string)),Free());
}int main()
{test();system("pause");return 0;
}
转载于:https://blog.51cto.com/11142019/1846847
shared_ptr循环引用定置删除器相关推荐
- C++ 智能指针 :内存泄漏、 RAII、智能指针、auto_ptr、unique_ptr、shared_ptr、weak_ptr、定制删除器deleter
文章目录 内存泄漏 什么是内存泄漏 内存泄漏的危害: 如何避免内存泄漏 RAII 智能指针 auto_ptr unique_ptr shared_ptr 循环引用问题 weak_ptr 定制删除器 内 ...
- 深入学习c++--智能指针(二) weak_ptr(打破shared_ptr循环引用)
1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智 ...
- shared_ptr 循环引用问题以及解决办法
栗子 #include <iostream> #include <memory>class CB; class CA { public:CA() { std::cout < ...
- 16.3 shared_ptr常用操作、计数与自定义删除器等
一:shared_ptr引用计数的增加和减少 共享式引用计数,每一个shared_ptr的拷贝都指向相同的内容(对象),只有最后一个指向该对象的shared_ptr指针不需要. 在指向该对象的时候,这 ...
- python 引用计数 循环引用_Python对象的循环引用问题
Python对象循环引用 我们来介绍一下 Python 是采用何种途径解决循环引用问题的. 循环引用垃圾回收算法 上图中,表示的是对象之间的引用关系,从自对象指向他对象的引用用黑色箭头表示.每个对象里 ...
- vsto excel 表格存在循环引用 删除名称管理器很慢
vsto excel 表格存在循环引用 删除名称管理器很慢 删除即可 private void ClearCircleReference(Excel.Worksheet sheet){Excel.Ra ...
- [C++11]共享智能指针shared_ptr指定删除器
当智能指针管理的内存对应的引用计数变为 0 的时候,这块内存就会被智能指针析构掉了.另外,我们在初始化智能指针的时候也可以自己指定删除动作,这个删除操作对应的函数被称之为删除器,这个删除器函数本质是一 ...
- Cpp / shared_ptr 配置删除器的方法
一.普通函数 void Deleter(T *x) {delete[] x; }std::shared_ptr<T> p1(new T[5], Deleter); 二.仿函数 class ...
- spring生命周期七个过程_Spring杂文(三)Spring循环引用
众所周知spring在默认单例的情况下是支持循环引用的 Appconfig.java类的代码 @Configurable @ComponentScan("com.sadow") p ...
最新文章
- splay + 线段树 ---- P3765总统选举 [带修改的动态区间众数 摩尔投票+n棵splay]
- mysql忘记密码,如何重置密码
- 使用SAP C4C rule editor动态控制UI上某个按钮是否显示
- 02.规划过程组表格-需求管理计划
- org.xml.sax.SAXParseException; lineNumber: 11; columnNumber: 285; cvc-elt.1.a: 找不到元素 ‘beans‘ 的声明。
- 64位ubuntu 12.04系统编译busybox遇到的问题处理办法
- 故意向Linux内核提交漏洞被全线拉黑?华人教授行为引众怒
- 日志分析工具 Log Parser
- 全阶滑模观测器程序_滑模观测器转子估算程序
- 晨哥真有料丨这样的你很掉价!
- 中国平安云桌面的地址
- Google Java编程风格指南中文版(转)
- 25年前的预言(转贴一篇,事实胜于雄辩)
- R-大数据分析挖掘(4-R爬虫实现)
- 我用.Net做的一些系统及参与测试的系统
- 2020-09-20
- Python一周小结
- PR音频处理——收尾音乐
- 草莓熊python turtle绘图(风车版)附源代码
- Ardunio开发实例-L9110直流电机驱动模块