天天看點

[C++] 程式設計實踐之1: Google的C++代碼風格4:來自Google的奇技

##來自Google的奇技

  Google用了很多自己實作的技巧/工具使C++代碼更加簡裝,我們使用C++的方式可能和你在氣他地方見到的有所不同。

###所有權與智能指針

動态配置設定出的對象最好有單一且固定的所有主(owner),且通過智能指針傳遞所有權(ownership)。

定義:

  • 所有權是一種登記/管理動态記憶體和其它資源的技術。動态配置設定出的對象的所有主是一個對象或者函數,後者負責確定目前者無用時就自動銷毀前者。所有權有時候可以共享,那麼就由最後一個所有主來負責銷毀它。甚至也可以不同共享,在代碼中直接把所有權傳遞給其它對象。
  • 其實您可以把智能指針當成一個重載了*和->的“對象”來看。智能指針類型被用來自動化所有權的登記工作,來確定執行銷毀義務到位。std::unique_ptr是C++11新推出的一種智能指針類型,用來表示動态配置設定出的對象的“獨一無二”的所有權;當std::unique_ptr離開作用域,對象就會被銷毀。不能複制std::unique_ptr,但是可以把它移動給新所有主。std::shared_ptr同樣表示動态配置設定對象的所有權,但是可以被共享,也可以被複制;對象的所有權由所有複制者共同擁有,最後一個複制者被銷毀時,對象也會随着被銷毀。

優點:

  • 如果沒有清晰、邏輯條理所有權安排,不可能管理好動态配置設定的記憶體。
  • 傳遞對象的所有權,其開銷比複制來的小,如果可以複制的話。
  • 傳遞所有權也比“借用”指針或者引用來的簡單,畢竟它大大省去了兩個使用者一起協調對象生命周期的工作。
  • 如果所有權邏輯有條理,有文檔且不亂來的話,可讀性很棒。
  • 可以不用手動完成所有權的登記工作,大大簡化了代碼,也免去了一大波錯誤之煩惱。
  • 對于const對象來說,智能指針簡單易用,也比深度複制高效。

缺點:

  • 不得不用指針(不管是智能指針還是原生指針)來表示和傳遞所有權。指針予以可要比值語義複雜得多了,特别實在API裡:你不僅要操心所有權,還要顧及别名,生命周期,可變性(mutability)以及其它大大小小的問題。
  • 其實值語義的開銷經常被高估,是以就所有權的性能來說,可不能光隻考慮可讀性以及複雜性。
  • 如果API依賴所有權的傳遞,就會害得用戶端不得不用單一的記憶體管理模型。
  • 銷毀資源并回收的相關代碼不是很明朗。
  • std::unique_ptr的所有關傳遞原理是C++11的move文法,後者畢竟是剛剛剛推出的,容易迷惑程式員。
  • 如果原本的所有權設計已經夠完善了,那麼若要引入所有權共享機制,可能不得不重構整個系統。
  • 所有有關共享機制的登記工作在運作時進行,開銷可能相當不小。
  • 某些極端情況下,所有權被共享的對象永遠不會被銷毀,比如引用死循環(cyclic reference)。
  • 智能指針并不能夠替代原生指針。

決定:

  • 如果必須使用動态配置設定,傾向于保持配置設定者的所有權。如果其他地方要使用這個對象,最好傳遞它的拷貝,或者傳遞一個不用改變所有權的指針或者引用。傾向于使用std::unique_ptr來明确所有權傳遞,例如:
std::unique_ptr<Foo> FooFactory();
void FooConsumer(std::unique_ptr<Foo> ptr);
           

避免使用共享所有權。如果對性能要求很高,并且操作的對象是不可變的(比如說std::shared_ptr),這時可以用共享所有權來避免昂貴的拷貝操作。如果确實要使用共享所有權,傾向于使用std::shared_ptr。

  • 不要在新代碼中使用"scoped_ptr ‘’,除非你必須相容老版本的C++,總是用std::unique_ptr代替std::auto_ptr。

###cpplint

使用cpplint.py檢查風格錯誤。

cpplint.py是一個用來分析源檔案,能夠檢查出多種風格錯誤的工具。它并不完美,甚至還會漏報和誤報,但它仍然是一個非常有用的工具。在行尾加 // NOLINT,或者上一行加 // NOLINTNEXTLINE,可以忽略報錯。

  某些項目會指導你如何使用他們的項目工具運作cpplint.py。如果你參與的項目沒有提供,你可以單獨下載下傳cpplint.py。

###總結

  1. 把智能指針當成對象來看待的話,就很好領會它與所指對象之間的關系了。
  2. 原來Rust的Ownership思想是受到了C++智能指針的很大啟發。
  3. scoped_ptr和auto_ptr已經過時,現在是shared_ptr和unique_ptr的天下了。
  4. 按本文來說,似乎除了智能指針,還有氣他所有權機制,值得留意。
  5. Arch Linux使用者注意了,AUR有對cpplint打包。

繼續閱讀