大型專案開發:謹慎使用智慧指標
智慧指標使用上的問題
智慧指標的使用太普遍了,它讓程式設計師擺脫了記憶體管理的惡夢,但實際上智慧指標本身也可能引入另一個惡夢。主要包括兩個問題點:
- 效能問題。因為需要引入一些變數(bookkeeping),甚至在多執行緒下的一些互斥操作,它所帶來的效能開銷往往比想像的要高。比如以智慧指標作為函式引數以及返回值時。
- 物件釋放的時機不明確。比如std::auto_ptr,總讓人感覺不明不白。而有時一些迴圈引用,又會導致記憶體洩露。
所以即便有了智慧指標,程式設計師還是要認真考慮使用它們的時機。
智慧指標的本質是所有權管理
所有權(Ownership)是一個用來管理動態分配記憶體的記錄(bookkeeping)技術。動態分配記憶體的所有者需要負責在所分配記憶體不再需要時釋放它。共享所有權時,最後一個owner負責清理。即使不是共享,也可以在程式碼間傳遞Ownership。
運用智慧指標的核心是保持所有權(Ownership)的明確、清晰。一般情況下是保證所有權的單一,無論是使用WeakPtr, Scoped Pointer都可以保持所有權的單一,這時所有權可以在不同的物件/程式碼段轉移。另一種情況就是需要共享所有權,比較常用的引用指數智慧指標,就是幫助完成共享所有權的。
概括起來三個要點:
1.區域性化
推薦保持單一、固定的所有權。當所有權需要在不同程式碼段間傳遞時,就要使用智慧指標。
2.明確的清理時機。
使用引用計數,和std::auto_ptr都會引發對釋放時機的疑問。有可能引入一些隱晦的Bug。當需要共享所有權時,一定要先思考這個設計的必要性,以及記憶體釋放的時機是否明確、清晰。
3.最好的方式不要使用指標。可以使用引用來代替指標。見後面WebKit的故事。
大型專案中的應用
Google Coding Style的約定
如果需要動態分配記憶體,儘量由分配的程式碼來持有所有權。
如果另一段程式碼需要訪問物件,先考慮傳遞物件拷貝,指標或者引用,而不是傳遞所有權。如果確有需要時,建議使用std::unique_ptr來顯示的傳遞所有權(使用std::move())。
除非有好的理由,否則不要共享所有權。比如為了避免複製。這時需要確定有明顯的效能收益,而且所持有的物件最好是隻讀的, 同時建議使用std::shared_ptr:
std::shared_ptr<const Foo>;
新程式碼裡不要再使用scoped_ptr,更不要使用std::auto_ptr, 而是使用std::unique_ptr來代替。
WebKit的故事
WebKit文件記錄了他們使用引用計數指標的故事,詳情見:RefPtr Basics。大意為:
早在2005年時為了解決記憶體洩露問題,開始使用基於引用計數的智慧指標,但是它有效能問題,特別是當作函式引數和返回值傳遞時。後來使用C++11提供move語義(即轉移所有權的方式)來解決了這個問題。(另外shared_ptr const & 的形式也可以避免不必要的引用計數操作。)
而到了2013年,WebKit的開發者發現氾濫的判空和有效性檢查,於是開始傾向於儘可能地使用引用(注意:不是引用計數指標), 而不是指標。
小結
解決記憶體問題的最佳的途徑仍然是由程式設計師管理好物件的生命週期。使用智慧指標也是有成本的,同時也會引入一些新問題,所以需要遵循一些約定來使用。Google Chromium/Webkit都有相應用的定義:
另外明確約定一個函式是否會返回空指標,特別是對於API來說,也會幫助使用者避免一些不必要的判空處理和一些隱晦的Bug。
進一步學習:
相關文章
- 大型專案開發: 標頭檔案順序
- 【Lambda、SteamAPI】謹慎使用流API
- 直播平臺開發難嗎?自己開發須謹慎
- 請謹慎使用sp_executesqlSQL
- AIX系統謹慎使用reboot命令AIboot
- STL程式設計實踐一:謹慎使用下標運算子 (轉)程式設計
- oracle中要謹慎使用update交叉更新!Oracle
- java流操作要謹慎Java
- Linux需要謹慎使用的幾個命令Linux
- 安全機構建議奧巴馬政府謹慎使用開源軟體
- 如何在大型專案中使用Git子模組開發Git
- 謹慎做資料庫技術的標準化(轉)資料庫
- 為什麼要謹慎使用Linux find命令?Linux
- JAVA基礎:謹慎使用Date和Time類(轉)Java
- 技術人,請謹慎跳槽!
- 網付智慧數字經營系統,代理需謹慎
- 謹慎處理 Service Worker 的更新
- UNIX下VG遷移(謹慎) - 轉
- 升級oracle一定要謹慎Oracle
- AIX強制關機需要謹慎AI
- 從Go、Swift出發:語言的選擇需謹慎GoSwift
- react-native大型專案開發實踐React
- 開發維護大型 Java 專案的建議Java
- 高峰期謹慎編譯業務物件編譯物件
- 新程式語言選擇需謹慎
- 搞程式有風險 修bug需謹慎
- 智慧指標指標
- 微軟今日徹底放棄Windows XP 繼續使用需謹慎微軟Windows
- 【SQL*Plus】在SQL*Plus中謹慎使用Ctrl+S快捷鍵SQL
- 話說智慧指標發展之路指標
- mpvue開發大型體育專案及總結記Vue
- 開發維護大型專案的Java的建議Java
- 給開發維護大型專案開發者的建議
- 第55條:謹慎地進行優化優化
- 【警鐘】謹慎刪除歸檔日誌
- DBA要謹慎關閉資料庫(轉)資料庫
- 育碧正在開發大型3A級VR專案,或將使用旗下知名IPVR
- 蘋果AirPods耳機補買一隻599元 謹慎使用蘋果AI