网站架构分析,海南海口最新新闻事件,网站关于我们页面设计,做网店的网站shared_ptr解决了scoped_ptr管理单个对象的缺陷#xff0c;且解决了防拷贝的问题。shared_ptr可以管理多个对象#xff0c;并且实现了资源共享。
但是仍然存在一些问题#xff0c;比如#xff0c;我们熟悉的双向链表#xff1a; struct Node { Node(const int value…shared_ptr解决了scoped_ptr管理单个对象的缺陷且解决了防拷贝的问题。shared_ptr可以管理多个对象并且实现了资源共享。
但是仍然存在一些问题比如我们熟悉的双向链表 struct Node { Node(const int value) :_pNext(NULL) ,_pPre(NULL) ,_value(value) {} Node* _pNext; Node* _pPre; int _value; };
这个双向链表对于shared_ptr会有什么影响呢
1、shared_ptr的循环引用问题
先看如下代码 #includeiostream
using namespace std;
#includeboost/shared_ptr.hpp
templatetypename T
class Node
{
public:Node(const T value):_pNext(NULL),_pPre(NULL)_value(value){}shared_ptrNodeT _pNext;shared_ptrNodeT _pPre;T _value;
};void FunTest()
{shared_ptrNodeint sp1(new Nodeint(1));shared_ptrNodeint sp2(new Nodeint(2));coutsp1.use_count()endl;coutsp2.use_count()endl;sp1-_pNext sp2;sp2-_pPre sp1;coutsp1.use_count()endl;coutsp2.use_count()endl;
}运行结果: 这就是shared_ptr实现的双向链表的模型在此处引起了循环引用的问题。
如图 当分别创建完sp1,sp2后它们各自的use_count为1当再次执行 sp1-_pNext sp2;sp2-_pPre sp1;这两句后sp1,sp2的use_count分别加为2
此时析构对象时use_count会减为1但不等于0所以它不会释放这就导致了循环引用问题。
那么如何解决循环引用问题呢我们又引出了另外一个智能指针weak_ptr(它是一个弱指针用来和shared_ptr搭配使用的)
2、解决循环引用问题 #includeiostream
using namespace std;
#includeboost/shared_ptr.hpp
templatetypename T
class Node
{
public:Node(const T value):_value(value){}T _value;weak_ptrNodeT _pNext;weak_ptrNodeT _pPre;
};void FunTest()
{shared_ptrNodeint sp1(new Nodeint(1));shared_ptrNodeint sp2(new Nodeint(2));coutsp1.use_count()endl;coutsp2.use_count()endl;sp1-_pNext sp2;sp2-_pPre sp1;coutsp1.use_count()endl;coutsp2.use_count()endl;
}运行结果 其实在shared_ptr和weak_ptr的引用计数的基类中有两个计数一个是_Uses,一个是_Weaks; shared_ptr当指向一片区域时引用计数会使用_Uses来;
weak_ptr:当指向一片区域时引用计数会使用_Weaks来;
最终看的还是use_count使用weak_ptr时use_count仍为1所以析构时可以成功释放。
3、定置删除器
原理对于像文件类型的指针用shared_ptr释放时无法释放因为在底层没有对文件指针的直接释放,所以得自己手动将其close掉。
void FunTest() { FILE* file fopen(1.txt,r); shared_ptrFILE sp(file); }
这时就要使用我们的定置删除器此处用了STL的六大组件之一-----仿函数
//成功的关闭文件 #includeiostream
using namespace std;
#includeboost/shared_ptr.hppstruct FClose
{void operator()(FILE *file){fclose(file);coutfclose()endl;}
};void FunTest()
{FILE* file fopen(1.txt,w);shared_ptrFILE sp(file,FClose());
}//类似的对于我们malloc出来的空间需要free掉时同样也可以用仿函数的形式 struct Free
{void operator()(void *ptr){free(ptr);coutfree()endl;}
};
void FunTest()
{int *p (int *)malloc(sizeof(int));shared_ptrint sp(p,Free());
}4、冒泡排序的升级版仿函数的形式 有时候当面试官让你写一个冒泡排序的时候你不知道面试官到底让你写的是升序还是降序此时就比较尴尬了哈你可以问一下面试官也是可以的当然还有一种更巧妙的方法就是你可以用仿函数的方式把两种方式都实现了需要哪种用哪种即可。 #includeiostream
using namespace std;
templatetypename T
class Greater
{
public:bool operator()(const Tleft,const T right){return leftright;}
};
templatetypename T
class Less
{
public:bool operator()(const Tleft,const T right){return leftright;}
};templatetypename T,typename Fun
void BubbleSort(T arr[],size_t size)
{for(size_t i 0; i size-1; i){for(size_t j 0; j size-i-1;j){if(Fun()(arr[j],arr[j1])){T tmp arr[j];arr[j] arr[j1];arr[j1] tmp;}}}}
void FunTest()
{int arr[] {2,5,4,1,6,9,8,7};BubbleSortint,Greaterint(arr,sizeof(arr)/sizeof(arr[0]));BubbleSortint,Lessint(arr,sizeof(arr)/sizeof(arr[0]));
}
int main()
{FunTest();return 0;
}如果可以写成这种程度肯定会使面试官眼前一亮。哈哈