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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

c++详解【智能指针】

發(fā)布時(shí)間:2023/11/30 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++详解【智能指针】 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

智能指針?是一個(gè)指針嗎?這里給大家說(shuō)的是,它不是一個(gè)指針,但它模擬了指針?biāo)哂械墓δ堋D敲?#xff0c;為什么要有智能指針的引入呢?看看下面的例子吧~

void FunTest() {int *p = new int[10];FILE *pFile = fopen("1.txt","r");if(pFile == NULL){return;}if(p){delete[] p;p = NULL;} } 在c++動(dòng)態(tài)內(nèi)存分配空間時(shí),是由用戶(hù)自己維護(hù)的,所以當(dāng)new出來(lái)空間后,必須由用戶(hù)手動(dòng)釋放。再看看上面的這個(gè)代碼,有什么問(wèn)題呢?顯然的,當(dāng)1.txt這個(gè)文件不存在時(shí),pFile就為空,這就使后面釋放p的語(yǔ)句沒(méi)有執(zhí)行,導(dǎo)致內(nèi)存泄漏。那么怎么解決這類(lèi)問(wèn)題呢?

這就引入了我們重要的智能指針,所謂智能指針就是智能化的管理動(dòng)態(tài)開(kāi)辟的資源的釋放工作。

1、模擬實(shí)現(xiàn)auto_ptr

template<typename T> class AutoPtr { public:AutoPtr(T* p):_p(new T(1)){cout<<"AutoPtr()"<<endl;_p = p;}AutoPtr(AutoPtr& ap):_p(ap._p){cout<<"AutoPtr(AutoPtr& ap)"<<endl;ap._p = NULL;}AutoPtr<T>& operator=(AutoPtr& ap){cout<<"AutoPtr<T>& operator=(AutoPtr& ap)"<<endl;if(this != &ap){delete _p;_a = ap._p;ap._p = NULL;}}~AutoPtr(){cout<<"~AutoPtr()"<<endl;if (_p){delete _p;_p = NULL;}} public:T& operator*(){return *_p;}T* operator->(){return _p;} private:T *_p; };void FunTest() {AutoPtr<int> ap = new int;AutoPtr<int> ap1(ap);*ap1 = 10;*(ap1.operator->()) = 20; } int main() {FunTest();return 0; }

智能指針AutoPtr的特點(diǎn)是:只可以管理一個(gè)對(duì)象,看一下監(jiān)視窗口:



這樣就會(huì)導(dǎo)致資源被轉(zhuǎn)移。

當(dāng)然,AutoPtr還有另一種實(shí)現(xiàn)方式:

template<typename T> class AutoPtr { public:AutoPtr(T* p):_p(new T(1)){cout<<"AutoPtr()"<<endl;_p = p;_owner = true;}AutoPtr(AutoPtr& ap):_p(ap._p){cout<<"AutoPtr(AutoPtr& ap)"<<endl;ap._owner = false;ap._p = NULL;_owner = true;}AutoPtr<T>& operator=(AutoPtr& ap){cout<<"AutoPtr<T>& operator=(AutoPtr& ap)"<<endl;if(this != &ap){delete _p;_a = ap._p;ap._owner = false;ap._p = NULL;_owner = true;}}~AutoPtr(){cout<<"~AutoPtr()"<<endl;if (_p){delete _p;_p = NULL;_owner = false;}} public:T& operator*(){return *_p;}T* operator->(){return _p;} private:T *_p;bool _owner; };void FunTest() {AutoPtr<int> ap = new int;AutoPtr<int> ap1(ap);*ap1 = 10;*(ap1.operator->()) = 20;}int main() {FunTest();return 0; }

這種方式就是定義一個(gè)私有成員,用來(lái)標(biāo)記當(dāng)前對(duì)象的狀態(tài),若為false,表示當(dāng)前對(duì)象已不再指向任何空間,若為true,說(shuō)明該對(duì)象指向申請(qǐng)的那塊內(nèi)存。



那么,這種類(lèi)型的指針有什么弊端嗎?首先,只能管理單個(gè)對(duì)象,每次只有一個(gè)對(duì)象可使用申請(qǐng)的空間。其次,使得資源轉(zhuǎn)移,另一個(gè)對(duì)象使用時(shí),前一個(gè)對(duì)象將賦為空。

但是切記不要使用auto_ptr

2、模擬實(shí)現(xiàn)scoped_ptr

scoped_ptrauto_ptr一樣,都是管理單個(gè)對(duì)象的。它的作用是:在一個(gè)類(lèi)中防止拷貝。說(shuō)起防止拷貝,大家會(huì)想到把它定義為私有的,總可以了吧。其實(shí)并不可以,因?yàn)樵L問(wèn)私有成員或函數(shù)的方式還有將調(diào)用它的函數(shù)聲明為類(lèi)的友元就ok啦。所以,在這里,我們將學(xué)到一種防拷貝的方式:只聲明不定義,且將拷貝構(gòu)造和賦值運(yùn)算符重載聲明為私有即可。

實(shí)現(xiàn)如下:

template<typename T> class ScopedPtr { public:ScopedPtr(const T* p):_p(p){}~ScopedPtr(){if(_p){delete _p;_p = NULL;}}T& operator*(){return *_p;}T* operator->(){return _p;} private:ScopedPtr(const ScopedPtr&);ScopedPtr<T>& operator=(const ScopedPtr&); private:T* _p; };void FunTest() {ScopedPtr<int> sp = new int;ScopedPtr<int> sp1(sp); //error,這樣就使用不了拷貝構(gòu)造函數(shù)了ScopedPtr<int> sp1 = sp; //error,使用不了賦值運(yùn)算符重載}int main() {FunTest();return 0; }

scoped_ptr實(shí)現(xiàn)的機(jī)制體現(xiàn)了它的獨(dú)占性,當(dāng)一個(gè)對(duì)象占用一塊空間時(shí),其他對(duì)象將無(wú)法使用。并且解決了不讓資源轉(zhuǎn)移的問(wèn)題。

注:在STL源碼庫(kù)中使用的是scoped_ptr,而在boost庫(kù)中,使用的是unique_ptr。兩個(gè)其實(shí)是一樣的。

3、模擬實(shí)現(xiàn)shared_ptr

前面兩個(gè)智能指針都是管理單個(gè)對(duì)象,而這個(gè)shared_ptr則是可以管理多個(gè)對(duì)象。它們之間的資源是共享的。

以下代碼是使用引用計(jì)數(shù)的方式實(shí)現(xiàn)資源共享。

實(shí)現(xiàn)代碼如下:

template<typename T> class SharedPtr { public:SharedPtr(T* p = NULL):_p(p),_pCount(new int(1)){cout<<"SharedPtr(T* p = NULL)"<<endl;}SharedPtr(SharedPtr& sp):_p(sp._p),_pCount(sp._pCount){cout<<"SharedPtr(SharedPtr& sp)"<<endl;}SharedPtr<T>& operator=(const SharedPtr& sp){cout<<"SharedPtr<T>& operator=(const SharedPtr& sp)"<<endl;if(_p != sp._p){if(_p == NULL){_p = sp._p;_pCount = sp._pCount;}else if(_p && (*_pCount== 1)){delete _p;_p = sp._p;_pCount = sp._p;}else{--(*_pCount);_p = sp._p;_pCount = sp._pCount;}if(sp._p)++(*_pCount);}return *this;}~SharedPtr(){cout<<"~SharedPtr()"<<endl;if(_p && --(*_pCount) == 0){delete _p;_p = NULL;}} public:T& operator*(){return *_p;}T* operator->(){return _p;}int UseCount(){if(_pCount != NULL)return *_pCount;return 0;}private:T *_p;int *_pCount; };void FunTest() {SharedPtr<int> sp = new int(1);SharedPtr<int> sp1(sp);SharedPtr<int> sp2;sp = sp1;sp2 = sp1;cout<<sp.UseCount()<<endl;cout<<sp1.UseCount()<<endl;cout<<sp2.UseCount()<<endl; }int main() {FunTest();return 0; }
運(yùn)行結(jié)果:



此版本雖然實(shí)現(xiàn)了共享,但也存在著不少問(wèn)題,比如線程安全問(wèn)題、循環(huán)引用問(wèn)題,定置刪除器問(wèn)題等。這幾個(gè)問(wèn)題我們下一篇再詳細(xì)解說(shuō)哦。


希望大家可以對(duì)博客提出寶貴意見(jiàn),歡迎來(lái)訪哦。







總結(jié)

以上是生活随笔為你收集整理的c++详解【智能指针】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。