首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Google C++ 風格指南(四):智慧指標與 C++ 進階特性使用規範

     編輯:關於C++

Google 風格核心哲學:安全第一、便利第二、局部化管理

1. 智慧指標:優先 scoped_ptr,特定場景 shared_ptr,禁用 auto_ptr

  • 擁有權明確:優先直接以值/區域變數持有物件,無需指標。
  • scoped_ptr:單一擁有者,作用域結束自動釋放,**零額外開銷**。
  • shared_ptr (C++11 std::shared_ptr):僅用於 STL 容器共享擁有權,引用計數有效能成本且易循環引用。
  • 禁用 auto_ptr:複製語意詭異(所有權轉移),極易誤用。

2. 參考參數:輸入參數用 const T&,輸出參數用 T*

  • **強制規定**:函式參數表中所有參考**必須加 const**。
  • void Foo(const string& in, string* out);
  • 例外:bind2nd/mem_fun 等 STL 配接器不接受參考,須用指標。

3. 函式多載:僅限參數型別不同且功能相同

  • 優點:直觀、配合模板、方便呼叫端。
  • 缺點:呼叫端難判斷實際呼叫哪個多載;衍生類別部分覆寫易混淆。
  • **建議**:函式名包含參數資訊,如 AppendString()/AppendInt() 替代 Append() 多載。

4. 預設參數:禁止使用

  • 優點:減少函式定義數量。
  • 缺點:呼叫端程式碼隱藏實際傳遞參數;修改預設值影響範圍難控;複製貼上程式碼易遺漏參數。
  • **結論**:所有參數明確指定,強制呼叫端思考 API 契約。

5. 變長陣列 (VLA) 與 alloca():禁止

  • 非標準 C++,堆疊配置大小依賴執行期資料,**極易導致難以重現的堆疊溢位**(開發機正常、產品機掛掉)。
  • 改用安全配置器:scoped_ptr/scoped_array、std::vector。

6. Friend:合理使用

  • 同檔案定義,避免跨檔查找私有成員存取。
  • 典型用法:FooBuilder 為 Foo 的 friend 建構內部狀態;單元測試類別為待測類別 friend。
  • 優於將成員設為 public 破壞封裝。

7. 異常:禁止使用

  • 優點:建構函式失敗唯一處理方式;現代語言共通;第三方庫支援。
  • 缺點:控制流難追蹤;需 RAII 支撐;二進位膨脹;既有程式碼無異常安全保證,引入成本極高。
  • **決策**:Google 既有程式碼庫無異常處理,為一致性與整合成本考量**全面禁用**。Windows 平台 ATL/STL 例外見第八篇。

8. RTTI:禁止(單元測試除外)

  • 需求執行期型別識別通常意味著**設計缺陷**。
  • 替代方案:虛擬函式分派、Visitor 模式(雙重分派)。
  • 若必須用,三思後用 dynamic_cast,**勿手工實作類 RTTI 機制**。

9. 型別轉換:使用 C++ 風格 static_cast 等,禁用 C 風格

  • static_cast:數值轉換、明確向上轉型。
  • const_cast:移除 const。
  • reinterpret_cast:指標/整數不安全轉換,**極度謹慎**。
  • dynamic_cast:僅單元測試允許,其他場合說明設計有問題。

10. I/O 流:僅限日誌介面,其他用 printf/read/write

  • 流優點:型別安全、自動建構/解構檔案。
  • 流缺點:格式化困難(國際化 %1$s 不支援)、pread 等難實作、<< 重載易誤用(this vs *this)。
  • **統一性原則**:專案單一 I/O 風格,選擇 printf 族。

11. 前置遞增/遞減:迭代器/模板型別必用 ++i

後置形式需複製暫存值,迭代器複製成本高。純量型別無差異。

12. const:能用盡用,提倡前置 const int*

  • 參數/成員/函式/變數加 const 增加編譯期檢查層級。
  • 避免過度:const int * const * const x → const int** x 即可。
  • mutable 多執行緒不安全,慎用。

13. 整數型別:僅用 int,確定寬度用 <stdint.h> (int16_t 等),禁用無號型別表達非負數

  • int 至少 32 位,勿假設更大;需 64 位用 int64_t/uint64_t。
  • 無號型別陷阱:for (unsigned i=n-1; i>=0; --i) 無限迴圈;型別提升機制導致行為反直覺。
  • 用 assert(x >= 0) 保護非負語意,型別用有號整數。

14. 64 位相容性

  • printf 格式字串用 PRIuS/PRId64 等巨集(含 inttypes.h)。
  • sizeof(void*) != sizeof(int),指標大小整數用 intptr_t。
  • 結構體對齊:磁碟結構體 32/64 位對齊一致,用 __attribute__((packed)) 或 #pragma pack()。
  • 64 位常數後綴 LL/ULL。

15. 前處理巨集:慎用,優先內聯函式/常數/列舉

  • 巨集使編譯器見程式碼與開發者見程式碼不一致,易產生詭異行為。
  • 使用模式:.h 禁定義、用前 #define 用後 #undef、避免名稱衝突、避免不平衡 C++ 結構。

16. 0/NULL/nullptr:整數 0、浮點 0.0、指標 NULL (C++11 nullptr)、字元 '\0'

NULL 像指標,某些編譯器提供有用警告(sizeof(NULL) != sizeof(0))。

17. sizeof:優先 sizeof(varname),型別改變自動同步

Struct data; memset(&data, 0, sizeof(data));  // 佳
memset(&data, 0, sizeof(Struct));            // 型別改名易忘記更新

18. Boost 庫:僅允許認可子集

目前允許:Compressed Pair、Pointer Container (除 ptr_array/序列化)。積極評估擴充中。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved