Google C++ 程式設計風格指南:來自 Google 的奇技
Google 用了很多自己實現的技巧 / 工具使 C++ 程式碼更加健壯, 我們使用 C++ 的方式可能和你在其它地方見到的有所不同.
4.1. 所有權與智慧指標
動態分配出的物件最好有單一且固定的所有主(onwer), 且通過智慧指標傳遞所有權(ownership).
定義:
所有權是一種登記/管理動態記憶體和其它資源的技術。動態分配出的物件的所有主是一個物件或函式,後者負責確保當前者無用時就自動銷燬前者。所有權有時可以共享,那麼就由最後一個所有主來負責銷燬它。甚至也可以不用共享,在程式碼中直接把所有權傳遞給其它物件。
其實您可以把智慧指標當成一個過載了
*
和->
的「物件」來看。智慧指標型別被用來自動化所有權的登記工作,來確保執行銷燬義務到位。std::unique_ptr 是 C++11 新推出的一種智慧指標型別,用來表示動態分配出的物件的「獨一無二」所有權;當std::unique_ptr
離開作用域,物件就會被銷燬。不能複製std::unique_ptr
, 但可以把它移動(move)給新所有主。std::shared_ptr 同樣表示動態分配物件的所有權,但可以被共享,也可以被複制;物件的所有權由所有複製者共同擁有,最後一個複製者被銷燬時,物件也會隨著被銷燬。
優點:
- 如果沒有清晰、邏輯條理的所有權安排,不可能管理好動態分配的記憶體。
- 傳遞物件的所有權,開銷比複製來得小,如果可以複製的話。
- 傳遞所有權也比「借用」指標或引用來得簡單,畢竟它大大省去了兩個使用者一起協調物件生命週期的工作。
- 如果所有權邏輯條理,有文件且不亂來的話,可讀性很棒。
- 可以不用手動完成所有權的登記工作,大大簡化了程式碼,也免去了一大波錯誤之惱。
- 對於 const 物件來說,智慧指標簡單易用,也比深度複製高效。
缺點:
- 不得不用指標(不管是智慧的還是原生的)來表示和傳遞所有權。指標語義可要比值語義複雜得許多了,特別是在 API 裡:您不光要操心所有權,還要顧及別名,生命週期,可變性(mutability)以及其它大大小小問題。
- 其實值語義的開銷經常被高估,所以就所有權的效能來說,可不能光只考慮可讀性以及複雜性。
- 如果 API 依賴所有權的傳遞,就會害得客戶端不得不用單一的記憶體管理模型。
- 銷燬資源並回收的相關程式碼不是很明朗。
std::unique_ptr
的所有權傳遞原理是 C++11 的 move 語法,後者畢竟是剛剛推出的,容易迷惑程式設計師。- 如果原本的所有權設計已經夠完善了,那麼若要引入所有權共享機制,可能不得不重構整個系統。
- 所有權共享機制的登記工作在執行時進行,開銷可能相當不小。
- 某些極端情況下,所有權被共享的物件永遠不會被銷燬,比如引用死迴圈(cyclic references)。
- 智慧指標並不能夠完全代替原生指標。
決定:
如果必須使用動態分配,傾向於保持分配者的所有權。如果其他地方要使用這個物件,最好傳遞它的拷貝,或者傳遞一個不用改變所有權的指標或引用。傾向於使用 std::unique_ptr
來明確所有權傳遞,例如:
std::unique_ptr<Foo> FooFactory(); void FooConsumer(std::unique_ptr<Foo> ptr);
避免使用共享所有權。如果對效能要求很高,並且操作的物件是不可變的(比如說
std::shared_ptr<const Foo>
),這時可以用共享所有權來避免昂貴的拷貝操作。如果確實要使用共享所有權,傾向於使用std::shared_ptr
。不要在新程式碼中使用
scoped_ptr `` ,除非你必須相容老版本的C++。總是用 ``std::unique_ptr
代替std::auto_ptr
。
4.2. cpplint
使用 cpplint.py
檢查風格錯誤.
cpplint.py
是一個用來分析原始檔, 能檢查出多種風格錯誤的工具. 它不併完美, 甚至還會漏報和誤報, 但它仍然是一個非常有用的工具. 在行尾加 // NOLINT
, 或在上一行加 // NOLINTNEXTLINE
, 可以忽略報錯。
某些專案會指導你如何使用他們的專案工具執行 cpplint.py
. 如果你參與的專案沒有提供, 你可以單獨下載 cpplint.py.
譯者(acgtyrant)筆記
- 把智慧指標當成物件來看待的話,就很好領會它與所指物件之間的關係了。
- 原來 Rust 的 Ownership 思想是受到了 C++ 智慧指標的很大啟發啊。
scoped_ptr
和auto_ptr
已過時。 現在是shared_ptr
和uniqued_ptr
的天下了。- 按本文來說,似乎除了智慧指標,還有其它所有權機制,值得留意。
- Arch Linux 使用者注意了,AUR 有對 cpplint 打包。
本系列文章
相關文章
- Google C++ 程式設計風格指南:命名約定GoC++程式設計
- Google JavaScript 程式碼風格指南GoJavaScript
- Google JavaScript 風格指南GoJavaScript
- Google自動程式設計框架AutoML入門指南Go程式設計框架TOML
- 《Google 開源專案風格指南》中文版Go
- [譯] Google JavaScript 風格指南中 13 個值得注意的細節GoJavaScript
- 來自Google資深工程師的API設計最佳實踐Go工程師API
- 使用Google Guava快樂程式設計GoGuava程式設計
- Google官方應用程式架構指南Go架構
- GOOGLE RANKBRAIN 完整指南GoAI
- 3 個相見恨晚的 Google Colaboratory 奇技淫巧!Go
- Google 真賤格Go
- 《程式設計師漫畫》| 萌新面試Google程式設計師面試Go
- Google程式設計師的一天是如何度過的?Go程式設計師
- 各種流行的程式設計風格程式設計
- Google 是怎麼設計遊戲手柄的?Go遊戲
- #Google HTML&CSS規範指南GoHTMLCSS
- 如何培養良好的程式設計風格程式設計
- Vue 前端程式碼風格指南Vue前端
- 怎麼提高程式碼質量?-來自Google的研發經驗總結Go
- PEP 8 程式程式碼的編寫風格指南
- [譯] 無盡滾動的複雜度 — 來自 Google 大神的拆解複雜度Go
- java程式設計規約----程式碼風格(一)Java程式設計
- Google:Google Cloud再次打破了百萬億位的圓周率計算紀錄GoCloud
- 全圖文分析:如何利用Google的protobuf,來思考、設計、實現自己的RPC框架GoRPC框架
- Spring MVC 中使用 RESTFul 程式設計風格SpringMVCREST程式設計
- Google Summer of Code谷歌程式設計之夏活動流程全解析(上)Go谷歌程式設計
- Json風格指南JSON
- 推薦一份 Google 面試指南Go面試
- 前端程式碼規範 — JavaScript 風格指南前端JavaScript
- 「Adobe國際認證」想要設計!搞懂風格指南,就是你最好的入門設計
- Google報告:大量被入侵的 Google Cloud 例項被用來挖掘加密貨幣GoCloud加密
- 最小化的 Google Analytics 程式碼Go
- Java程式設計指南:高階技巧解析 - Excel單元格樣式的程式設計設定Java程式設計Excel
- Google Guava Stopwatch(計時器)GoGuava
- 編寫可維護的JavaScript-程式設計風格JavaScript程式設計
- 高質量C++/C程式設計指南(林銳)C++C程式程式設計
- Google:窺視消費者的未來2020Go
- 程式碼不止|想制勝海外市場?Google 來幫你!Go