點擊上方“C語言與CPP編程”,選擇“關(guān)注/置頂/星標(biāo)公眾號”
干貨福利,第一時間送達(dá)!
(資料圖片)
小伙伴們大家好,我是飛宇。
今天繼續(xù)更新《Effective C++》和《C++并發(fā)編程實戰(zhàn)》的讀書筆記,下面是已經(jīng)更新過的內(nèi)容:
《C++并發(fā)編程實戰(zhàn)》讀書筆記(1):并發(fā)、線程管控
《C++并發(fā)編程實戰(zhàn)》讀書筆記(2):并發(fā)操作的同步
《Effective C++》讀書筆記(2):構(gòu)造/析構(gòu)/賦值運算
《Effective C++》讀書筆記(1):讓自己習(xí)慣C++
所謂資源就是,一旦用了它,將來必須還給系統(tǒng),包括最常使用的動態(tài)分配內(nèi)存、文件描述符、互斥鎖等等。由于異常、函數(shù)內(nèi)多重回傳路徑、版本更改時遺漏等原因,任何時候都確保這一點是很難的。
本章總結(jié)了基于對象的一般化資源管理辦法以及一些專屬條款。嚴(yán)守這些做法幾乎可以消除資源管理問題。
條款13、以對象管理資源
假設(shè)你有一個工廠函數(shù)用來獲取一個動態(tài)分配對象,那么任何調(diào)用它的用戶有責(zé)任刪除這個對象:
上述some_function函數(shù)看似沒有問題,實際上仍有很多情況會導(dǎo)致不會執(zhí)行刪除操作,例如某個過早的return、某個異常、多個版本后維護人員遺忘了這一點等等。
為了確保動態(tài)獲取的資源一定會被釋放,可以用對象來管理資源,將獲取資源的行為放在構(gòu)造函數(shù)中,將釋放資源的行為放在析構(gòu)函數(shù)中;那么,不論程序如何運行,一定會執(zhí)行析構(gòu)函數(shù),一定會釋放資源。這種做法稱為RAII(Resource Acquisition Is Initialization,資源獲取即初始化)。
標(biāo)準(zhǔn)庫中的智能指針可以輔助管理資源,其中shared_ptr的資源可以共享,通過引用計數(shù)來控制行為,引用計數(shù)歸零時刪除資源,而unique_ptr獨享資源。更多的使用與實現(xiàn)可以查閱cppreference。
條款14、在資源管理類中小心coping行為
對于管理堆對象來說,上文的智能指針已經(jīng)足夠。但是很多資源并非基于堆,需要自己實現(xiàn)一個RAII類來管理,這時就需要考慮一個問題:怎么處理拷貝?通常有兩種思路:
1、禁止拷貝。很多資源被復(fù)制是不合理的,因此可以用條款6中的方法來禁止拷貝構(gòu)造/拷貝運算符。
2、對底層資源使用引用計數(shù)法。有時我們希望保有資源直到最后一個用戶使用完,這時就可以用shared_ptr代替裸指針來管理底層資源,用shared_ptr的刪除器來控制資源的析構(gòu)行為。
假設(shè)需要包裝Mutex互斥器,目前只有l(wèi)ock、unlock兩個函數(shù)。因為資源通過這兩個函數(shù)來獲取與釋放,不是通過堆,所以需要自己實現(xiàn)RAII類。
不過也有一些其他做法,例如將拷貝操作實現(xiàn)為深拷貝、將拷貝操作實現(xiàn)為轉(zhuǎn)移資源的擁有權(quán)等。
條款15、在資源管理類中提供對原始資源的訪問
各類API往往要求訪問原始資源,只提供了裸指針的接口,因此對于RAII類來說也應(yīng)該提供一個“取得其所管理之資源”的方法。或許有些破壞了類的封裝性質(zhì),但對于RAII類來說問題不大,因為根本上來說它只是為了管理資源的獲取與釋放。
至于如何訪問原始資源,一般分為顯式轉(zhuǎn)換與隱式轉(zhuǎn)換。
1、顯式轉(zhuǎn)換,例如shared_ptr的get函數(shù)。因為需要明確指定,所以比隱式轉(zhuǎn)換更安全。
2、隱式轉(zhuǎn)換,用法更自然,但可能出錯
條款16、成對使用new和delete時要采取相同形式
當(dāng)刪除指針時,為了讓delete知道要處理的是單個對象還是數(shù)組,如果new表達(dá)式使用[]則delete表達(dá)式也應(yīng)使用,如果new沒有使用則delete也不應(yīng)使用。
此外,為了避免失誤,最好不要為數(shù)組形式進行typedef/using。事實上,STL中的vector、array基本可以替代原生數(shù)組。
條款17、以獨立語句將newed對象置入智能指針
在函數(shù)傳參時new一個指針再初始化智能指針是不安全的:
考慮上面這個函數(shù)調(diào)用,假設(shè)f()出現(xiàn)異常,則前面申請的內(nèi)存將沒處釋放了。這種內(nèi)存泄露的本質(zhì)是當(dāng)申請數(shù)據(jù)指針后,沒有馬上傳給std::shared_ptr。
解決方法有兩個:1、在函數(shù)調(diào)用前先用獨立語句初始化shared_ptr,再傳給函數(shù)。2、函數(shù)傳參時使用make_shared來初始化智能指針,它只執(zhí)行一次內(nèi)存申請,更加異常安全。
你好,我是飛宇,本碩均于某中流985 CS就讀,先后于百度搜索以及字節(jié)跳動電商等部門擔(dān)任Linux C/C++后端研發(fā)工程師。
同時,我也是知乎博主@韓飛宇,日常分享C/C++、計算機學(xué)習(xí)經(jīng)驗、工作體會,歡迎點擊此處查看我以前的學(xué)習(xí)筆記&經(jīng)驗&分享的資源。
我組建了一些社群一起交流,群里有大牛也有小白,如果你有意可以一起進群交流。
歡迎你添加我的微信,我拉你進技術(shù)交流群。此外,我也會經(jīng)常在微信上分享一些計算機學(xué)習(xí)經(jīng)驗以及工作體驗,還有一些內(nèi)推機會。
加個微信,打開另一扇窗
標(biāo)簽:
(資料圖片)












