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循环引用定置删除器相关推荐

  1. C++ 智能指针 :内存泄漏、 RAII、智能指针、auto_ptr、unique_ptr、shared_ptr、weak_ptr、定制删除器deleter

    文章目录 内存泄漏 什么是内存泄漏 内存泄漏的危害: 如何避免内存泄漏 RAII 智能指针 auto_ptr unique_ptr shared_ptr 循环引用问题 weak_ptr 定制删除器 内 ...

  2. 深入学习c++--智能指针(二) weak_ptr(打破shared_ptr循环引用)

    1. 几种智能指针 1. auto_ptr: c++11中推荐不使用他(放弃) 2. shared_ptr: 拥有共享对象所有权语义的智能指针 3. unique_ptr: 拥有独有对象所有权语义的智 ...

  3. shared_ptr 循环引用问题以及解决办法

    栗子 #include <iostream> #include <memory>class CB; class CA { public:CA() { std::cout < ...

  4. 16.3 shared_ptr常用操作、计数与自定义删除器等

    一:shared_ptr引用计数的增加和减少 共享式引用计数,每一个shared_ptr的拷贝都指向相同的内容(对象),只有最后一个指向该对象的shared_ptr指针不需要. 在指向该对象的时候,这 ...

  5. python 引用计数 循环引用_Python对象的循环引用问题

    Python对象循环引用 我们来介绍一下 Python 是采用何种途径解决循环引用问题的. 循环引用垃圾回收算法 上图中,表示的是对象之间的引用关系,从自对象指向他对象的引用用黑色箭头表示.每个对象里 ...

  6. vsto excel 表格存在循环引用 删除名称管理器很慢

    vsto excel 表格存在循环引用 删除名称管理器很慢 删除即可 private void ClearCircleReference(Excel.Worksheet sheet){Excel.Ra ...

  7. [C++11]共享智能指针shared_ptr指定删除器

    当智能指针管理的内存对应的引用计数变为 0 的时候,这块内存就会被智能指针析构掉了.另外,我们在初始化智能指针的时候也可以自己指定删除动作,这个删除操作对应的函数被称之为删除器,这个删除器函数本质是一 ...

  8. Cpp / shared_ptr 配置删除器的方法

    一.普通函数 void Deleter(T *x) {delete[] x; }std::shared_ptr<T> p1(new T[5], Deleter); 二.仿函数 class ...

  9. spring生命周期七个过程_Spring杂文(三)Spring循环引用

    众所周知spring在默认单例的情况下是支持循环引用的 Appconfig.java类的代码 @Configurable @ComponentScan("com.sadow") p ...

最新文章

  1. splay + 线段树 ---- P3765总统选举 [带修改的动态区间众数 摩尔投票+n棵splay]
  2. mysql忘记密码,如何重置密码
  3. 使用SAP C4C rule editor动态控制UI上某个按钮是否显示
  4. 02.规划过程组表格-需求管理计划
  5. org.xml.sax.SAXParseException; lineNumber: 11; columnNumber: 285; cvc-elt.1.a: 找不到元素 ‘beans‘ 的声明。
  6. 64位ubuntu 12.04系统编译busybox遇到的问题处理办法
  7. 故意向Linux内核提交漏洞被全线拉黑?华人教授行为引众怒
  8. 日志分析工具 Log Parser
  9. 全阶滑模观测器程序_滑模观测器转子估算程序
  10. 晨哥真有料丨这样的你很掉价!
  11. 中国平安云桌面的地址
  12. Google Java编程风格指南中文版(转)
  13. 25年前的预言(转贴一篇,事实胜于雄辩)
  14. R-大数据分析挖掘(4-R爬虫实现)
  15. 我用.Net做的一些系统及参与测试的系统
  16. 2020-09-20
  17. Python一周小结
  18. PR音频处理——收尾音乐
  19. 草莓熊python turtle绘图(风车版)附源代码
  20. Ardunio开发实例-L9110直流电机驱动模块

热门文章

  1. python爬虫项目-33个Python爬虫项目实战(推荐)
  2. python入门练习题-Python简单新手入门练习题
  3. SPOJ Supernumbers in a permutation(LIS)
  4. UVa1153 Keep The Customer Satisfied(贪心)
  5. stl中的list学习笔记
  6. 题目1112:拦截导弹
  7. git创建、切换、合并、删除分支
  8. ReactNative环境配置的坑
  9. 四.Android adb命令(持续更新...)
  10. 向Lucene增加中文分词功能