日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++【深度剖析shared_ptr】

發布時間:2023/11/30 c/c++ 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++【深度剖析shared_ptr】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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的循環引用問題

先看如下代碼:

#include<iostream> using namespace std; #include<boost/shared_ptr.hpp> template<typename T> class Node { public:Node(const T& value):_pNext(NULL),_pPre(NULL)_value(value){}shared_ptr<Node<T>> _pNext;shared_ptr<Node<T>> _pPre;T _value; };void FunTest() {shared_ptr<Node<int>> sp1(new Node<int>(1));shared_ptr<Node<int>> sp2(new Node<int>(2));cout<<sp1.use_count()<<endl;cout<<sp2.use_count()<<endl;sp1->_pNext = sp2;sp2->_pPre = sp1;cout<<sp1.use_count()<<endl;cout<<sp2.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、解決循環引用問題

#include<iostream> using namespace std; #include<boost/shared_ptr.hpp> template<typename T> class Node { public:Node(const T& value):_value(value){}T _value;weak_ptr<Node<T>> _pNext;weak_ptr<Node<T>> _pPre; };void FunTest() {shared_ptr<Node<int>> sp1(new Node<int>(1));shared_ptr<Node<int>> sp2(new Node<int>(2));cout<<sp1.use_count()<<endl;cout<<sp2.use_count()<<endl;sp1->_pNext = sp2;sp2->_pPre = sp1;cout<<sp1.use_count()<<endl;cout<<sp2.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_ptr<FILE> sp(file);
}

這時,就要使用我們的定置刪除器:(此處用了STL的六大組件之一-----仿函數)

//成功的關閉文件:

#include<iostream> using namespace std; #include<boost/shared_ptr.hpp>struct FClose {void operator()(FILE *file){fclose(file);cout<<"fclose()"<<endl;} };void FunTest() {FILE* file = fopen("1.txt","w");shared_ptr<FILE> sp(file,FClose()); }

//類似的,對于我們malloc出來的空間,需要free掉時,同樣也可以用仿函數的形式:

struct Free {void operator()(void *ptr){free(ptr);cout<<"free()"<<endl;} }; void FunTest() {int *p = (int *)malloc(sizeof(int));shared_ptr<int> sp(p,Free()); }

4、冒泡排序的升級版(仿函數的形式)

有時候,當面試官讓你寫一個冒泡排序的時候,你不知道面試官到底讓你寫的是升序還是降序,此時就比較尷尬了哈,你可以問一下面試官也是可以的,當然還有一種更巧妙的方法就是:你可以用仿函數的方式,把兩種方式都實現了,需要哪種用哪種即可。

#include<iostream> using namespace std; template<typename T> class Greater { public:bool operator()(const T&left,const T& right){return left>right;} }; template<typename T> class Less { public:bool operator()(const T&left,const T& right){return left<right;} };template<typename 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[j+1])){T tmp = arr[j];arr[j] = arr[j+1];arr[j+1] = tmp;}}}} void FunTest() {int arr[] = {2,5,4,1,6,9,8,7};BubbleSort<int,Greater<int>>(arr,sizeof(arr)/sizeof(arr[0]));BubbleSort<int,Less<int>>(arr,sizeof(arr)/sizeof(arr[0])); } int main() {FunTest();return 0; }

如果可以寫成這種程度,肯定會使面試官眼前一亮。哈哈


總結

以上是生活随笔為你收集整理的c++【深度剖析shared_ptr】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。