




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第c++智能指針的超詳細(xì)講解目錄1.什么是智能指針2.原始指針的問題3.unique_ptr4.shared_ptr5.shared_ptr使用需要注意的點5.1不能將一個原始指針初始化多個shared_ptr5.2.循環(huán)引用問題6.智能指針小結(jié)總結(jié)
1.什么是智能指針
從比較簡單的層面來看,智能指針是RAII(ResourceAcquisitionIsInitialization,資源獲取即初始化)機(jī)制對普通指針進(jìn)行的一層封裝。這樣使得智能指針的行為動作像一個指針,本質(zhì)上卻是一個對象,這樣可以方便管理一個對象的生命周期。
在c++中,智能指針一共定義了4種:
auto_ptr、unique_ptr、shared_ptr和weak_ptr。其中,auto_ptr在C++11已被摒棄,在C++17中已經(jīng)移除不可用。
2.原始指針的問題
原始指針的問題大家都懂,就是如果忘記刪除,或者刪除的情況沒有考慮清楚,容易造成懸掛指針(danglingpointer)或者說野指針(wildpointer)。
我們看個簡單的例子
objtype*p=newobjtype();
p-func();
deletep;
上面的代碼結(jié)構(gòu)是我們經(jīng)??吹降?。里面的問題主要有以下兩點:
1.代碼的最后,忘記執(zhí)行deletep的操作。
2.第一點其實還好,比較容易發(fā)現(xiàn)也比較容易解決。比較麻煩的是,如果func()中有異常,deletep語句執(zhí)行不到,這就很難辦。有的同學(xué)說可以在func中進(jìn)行刪除操作,理論上是可以這么做,實際操作起來,會非常麻煩也非常復(fù)雜。
此時,智能指針就可以方便我們控制指針對象的生命周期。在智能指針中,一個對象什么情況下被析構(gòu)或被刪除,是由指針本身決定的,并不需要用戶進(jìn)行手動管理,是不是瞬間覺得幸福感提升了一大截,有點幸福來得太突然的意思,終于不用我自己手動刪除指針了。
3.unique_ptr
unique_ptr是獨享被管理對象指針?biāo)袡?quán)(owership)的智能指針。unique_ptr對象封裝一個原始指針,并負(fù)責(zé)其生命周期。當(dāng)該對象被銷毀時,會在其析構(gòu)函數(shù)中刪除關(guān)聯(lián)的原始指針。
創(chuàng)建unique_ptr:
#includeiostream
#includestring
#includememory
usingnamespacestd;
voidf1(){
unique_ptrintp(newint(5));
cout*pendl;
}
上面的代碼就創(chuàng)建了一個unique_ptr。需要注意的是,unique_ptr沒有復(fù)制構(gòu)造函數(shù),不支持普通的拷貝和賦值操作。因為unique_ptr獨享被管理對象指針?biāo)袡?quán),當(dāng)p2,p3失去p的所有權(quán)時會釋放對應(yīng)資源,此時會執(zhí)行兩次deletep的操作。
voidf1(){
unique_ptrintp(newint(5));
cout*pendl;
unique_ptrintp2(p);
unique_ptrintp3=p;
}
對于p2,p3對應(yīng)的行,IDE會提示報錯
無法引用函數(shù)std::__1::unique_ptr_Tp,_Dp::unique_ptr(conststd::__1::unique_ptrint,std::__1::default_deleteint)[其中_Tp=int,_Dp=std::__1::default_deleteint](已隱式聲明)--它是已刪除的函數(shù)
unique_ptr雖然不支持普通的拷貝和賦值操作,但卻可以將所有權(quán)進(jìn)行轉(zhuǎn)移,使用std::move方法即可。
voidf1(){
unique_ptrintp(newint(5));
unique_ptrintp2=std::move(p);
//error,此時p指針為空:cout*pendl;
cout*p2endl;
unique最常見的使用場景,就是替代原始指針,為動態(tài)申請的資源提供異常安全保證。
objtype*p=newobjtype();
p-func();
deletep
前面我們分析了這部分代碼的問題,如果我們修改一下
unique_ptrobjtypep(newobjtype());
p-func();
deletep
此時我們只要unique_ptr創(chuàng)建成功,unique_ptr對應(yīng)的析構(gòu)函數(shù)都能保證被調(diào)用,從而保證申請的動態(tài)資源能被釋放掉。
4.shared_ptr
我們提到的智能指針,很大程度上就是指的shared_ptr,shared_ptr也在實際應(yīng)用中廣泛使用。它的原理是使用引用計數(shù)實現(xiàn)對同一塊內(nèi)存的多個引用。在最后一個引用被釋放時,指向的內(nèi)存才釋放,這也是和unique_ptr最大的區(qū)別。當(dāng)對象的所有權(quán)需要共享(share)時,share_ptr可以進(jìn)行賦值拷貝。
shared_ptr使用引用計數(shù),每一個shared_ptr的拷貝都指向相同的內(nèi)存。每使用他一次,內(nèi)部的引用計數(shù)加1,每析構(gòu)一次,內(nèi)部的引用計數(shù)減1,減為0時,刪除所指向的堆內(nèi)存。
std::shared_ptrintp4=newint(1)
上面這種寫法是錯誤的,因為右邊得到的是一個原始指針,前面我們講過shared_ptr本質(zhì)是一個對象,將一個指針賦值給一個對象是不行的。
voidf2(){
shared_ptrintp=make_sharedint
shared_ptrintp2(p);
shared_ptrintp3=p;
以上寫法都是可以的
voidf2(){
shared_ptrintp=make_sharedint
int*p2=p.get();
cout*p2endl;
上面的寫法,可以獲取shared_ptr的原始指針。
5.shared_ptr使用需要注意的點
5.1不能將一個原始指針初始化多個shared_ptr
voidf2(){
int*p0=newint(1);
shared_ptrintp1(p0);
shared_ptrintp2(p0);
cout*p1endl;
上面代碼就會報錯。原因也很簡單,因為p1,p2都要進(jìn)行析構(gòu)刪除,這樣會造成原始指針p0被刪除兩次,自然要報錯。
5.2.循環(huán)引用問題
shared_ptr最大的坑就是循環(huán)引用。引用網(wǎng)絡(luò)上的一個例子:
structFather
shared_ptrSonson_;
structSon
shared_ptrFatherfather_;
intmain()
autofather=make_sharedFather
autoson=make_sharedSon
father-son_=son;
son-father_=father;
return0;
}
該部分代碼會有內(nèi)存泄漏問題。原因是
1.main函數(shù)退出之前,F(xiàn)ather和Son對象的引用計數(shù)都是2。
2.son指針銷毀,這時Son對象的引用計數(shù)是1。
3.father指針銷毀,這時Father對象的引用計數(shù)是1。
4.由于Father對象和Son對象的引用計數(shù)都是1,這兩個對象都不會被銷毀,從而發(fā)生內(nèi)存泄露。
為避免循環(huán)引用導(dǎo)致的內(nèi)存泄露,就需要使用weak_ptr。weak_ptr并不擁有其指向的對象,也就是說,讓weak_ptr指向shared_ptr所指向?qū)ο螅瑢ο蟮囊糜嫈?shù)并不會增加。
使用weak_ptr就能解決前面提到的循環(huán)引用的問題,方法很簡單,只要讓Son或者Father包含的shared_ptr改成weak_ptr就可以了。
structFather
shared_ptrSonson_;
structSon
weak_ptrFatherfather_;
intmain()
autofather=make_sharedFather
autoson=make_sharedSon
father-son_=son;
son-father_=father;
return0;
}
1.main函數(shù)退出前,Son對象的引用計數(shù)是2,而Father的引用計數(shù)是1。
2.son指針銷毀,Son對象的引用計數(shù)變成1。
3.father指針銷毀,F(xiàn)ather對象的引用計數(shù)變成0,導(dǎo)致Father對象析構(gòu),F(xiàn)ather對象的析構(gòu)會導(dǎo)致它包含的son_指針被銷毀,這時Son對象的引用計數(shù)變成0,所以Son對象也會被析構(gòu)。
6.智能指針小結(jié)
我們該如何選擇智能指針:
如果程序要使用多個指向同一個對象的指針,應(yīng)選擇shared_ptr。這樣的情況包括
1.有一個指針數(shù)組,并使用一些輔助指針來標(biāo)示特定的元素,如最大的元素和最小的元素;
2.兩個對象包含都指向第三個對象的指針;
3.STL容器包含指針。很多STL算法都支持復(fù)制和賦值操作,這些操作可用于shared_ptr,但不能用于unique_ptr(編譯器發(fā)出warning)和auto_ptr(行為不確定)。如果你的編
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 研發(fā)中心場委托招聘合作協(xié)議
- 茶具研發(fā)與生產(chǎn)合作協(xié)議
- 財務(wù)離職保密及競業(yè)限制合同范本
- 餐飲連鎖品牌特許經(jīng)營區(qū)域保護(hù)協(xié)議書
- 特色餐廳廚房設(shè)計與施工承包合同
- 產(chǎn)業(yè)園區(qū)場合作經(jīng)營與產(chǎn)業(yè)布局協(xié)議
- 跨境電商跨境支付反欺詐風(fēng)險管理合同
- 旅游景區(qū)場地轉(zhuǎn)租管理服務(wù)協(xié)議
- 回流洗腸護(hù)理操作規(guī)范
- 2025年企業(yè)安全協(xié)議
- 設(shè)備工程師招聘筆試題及解答(某大型國企)2025年
- 國家職業(yè)技術(shù)技能標(biāo)準(zhǔn) 6-29-01-07 鄉(xiāng)村建設(shè)工匠 2024年版
- 舊水泥混凝土路面碎石化技術(shù)規(guī)程(山東省標(biāo)準(zhǔn)DB37T-1160-2009)
- 四川省成都市2024年小升初英語試卷(含答案)
- 渠道襯砌施工方案(渠道預(yù)制混凝土塊)
- 02S515排水檢查井圖集
- 《糖的變化(含練習(xí))》參考課件
- DL∕T 2528-2022 電力儲能基本術(shù)語
- 2024年安徽高考化學(xué)真題試卷(原卷版+含解析)
- 2024年遼寧省中考語文試卷(含答案解析)
- 四川省南充市2023-2024學(xué)年七年級下學(xué)期7月期末英語試題
評論
0/150
提交評論