<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Google編程風格指南(一)

C語言專家集中營 ? 來源:未知 ? 作者:李倩 ? 2018-09-27 17:57 ? 次閱讀

0. 扉頁

0.1 譯者前言

Google 經常會發布一些開源項目, 意味著會接受來自其他代碼貢獻者的代碼. 但是如果代碼貢獻者的編程風格與 Google 的不一致, 會給代碼閱讀者和其他代碼提交者造成不小的困擾. Google 因此發布了這份自己的編程風格指南, 使所有提交代碼的人都能獲知 Google 的編程風格.

翻譯初衷:

規則的作用就是避免混亂. 但規則本身一定要權威, 有說服力, 并且是理性的. 我們所見過的大部分編程規范, 其內容或不夠嚴謹, 或闡述過于簡單, 或帶有一定的武斷性.

Google 保持其一貫的嚴謹精神, 5 萬漢字的指南涉及廣泛, 論證嚴密. 我們翻譯該系列指南的主因也正是其嚴謹性. 嚴謹意味著指南的價值不僅僅局限于它羅列出的規范, 更具參考意義的是它為了列出規范而做的謹慎權衡過程.

指南不僅列出你要怎么做, 還告訴你為什么要這么做, 哪些情況下可以不這么做, 以及如何權衡其利弊. 其他團隊未必要完全遵照指南亦步亦趨, 如前面所說, 這份指南是 Google 根據自身實際情況打造的, 適用于其主導的開源項目. 其他團隊可以參照該指南, 或從中汲取靈感, 建立適合自身實際情況的規范.

我們在翻譯的過程中, 收獲頗多. 希望本系列指南中文版對你同樣能有所幫助.

我們翻譯時也是盡力保持嚴謹, 但水平所限, bug 在所難免. 有任何意見或建議, 可與我們取得聯系.

中文版和英文版一樣, 使用ArtisticLicense/GPL開源許可.

中文版修訂歷史:

2015-08 : 熱心的清華大學同學 @lilinsanity 完善了「類」章節以及其它一些小章節。至此,對 Google CPP Style Guide 4.45 的翻譯正式竣工。

2015-07 4.45 : acgtyrant 為了學習 C++ 的規范,順便重新翻譯了本 C++ 風格指南,特別是 C++11 的全新內容。排版大幅度優化,翻譯措辭更地道,添加了新譯者筆記。Google 總部 C++ 工程師 innocentim, 清華大學不愿意透露姓名的唐馬儒先生,大阪大學大學院情報科學研究科計算機科學專攻博士 farseerfc 和其它 Arch Linux 中文社區眾幫了譯者不少忙,謝謝他們。因為 C++ Primer 尚未完全入門,暫時沒有翻譯「類」章節和其它一些小章節。

2009-06 3.133 : YuleFox 的 1.0 版已經相當完善, 但原版在近一年的時間里, 其規范也發生了一些變化.

Yang.Y 與 YuleFox 一拍即合, 以項目的形式來延續中文版 :Google 開源項目風格指南 - 中文版項目.

主要變化是同步到 3.133 最新英文版本, 做部分勘誤和改善可讀性方面的修改, 并改進排版效果. Yang.Y 重新翻修, YuleFox 做后續評審.

2008-07 1.0 : 出自YuleFox 的 Blog, 很多地方摘錄的也是該版本.

0.2 背景

C++ 是 Google 大部分開源項目的主要編程語言. 正如每個 C++ 程序員都知道的, C++ 有很多強大的特性, 但這種強大不可避免的導致它走向復雜,使代碼更容易產生 bug, 難以閱讀和維護.

本指南的目的是通過詳細闡述 C++ 注意事項來駕馭其復雜性. 這些規則在保證代碼易于管理的同時, 也能高效使用 C++ 的語言特性.

風格, 亦被稱作可讀性, 也就是指導 C++ 編程的約定. 使用術語 “風格” 有些用詞不當, 因為這些習慣遠不止源代碼文件格式化這么簡單.

使代碼易于管理的方法之一是加強代碼一致性. 讓任何程序員都可以快速讀懂你的代碼這點非常重要. 保持統一編程風格并遵守約定意味著可以很容易根據 “模式匹配” 規則來推斷各種標識符的含義. 創建通用, 必需的習慣用語和模式可以使代碼更容易理解. 在一些情況下可能有充分的理由改變某些編程風格, 但我們還是應該遵循一致性原則,盡量不這么做.

本指南的另一個觀點是 C++ 特性的臃腫. C++ 是一門包含大量高級特性的龐大語言. 某些情況下, 我們會限制甚至禁止使用某些特性. 這么做是為了保持代碼清爽, 避免這些特性可能導致的各種問題. 指南中列舉了這類特性, 并解釋為什么這些特性被限制使用.

Google 主導的開源項目均符合本指南的規定.

注意: 本指南并非 C++ 教程, 我們假定讀者已經對 C++ 非常熟悉.

1. 頭文件

通常每一個.cc文件都有一個對應的.h文件. 也有一些常見例外, 如單元測試代碼和只包含main()函數的.cc文件.

正確使用頭文件可令代碼在可讀性、文件大小和性能上大為改觀.

下面的規則將引導你規避使用頭文件時的各種陷阱.

1.1. Self-contained 頭文件

Tip

頭文件應該能夠自給自足(self-contained,也就是可以作為第一個頭文件被引入),以.h結尾。至于用來插入文本的文件,說到底它們并不是頭文件,所以應以.inc結尾。不允許分離出-inl.h頭文件的做法.

所有頭文件要能夠自給自足。換言之,用戶和重構工具不需要為特別場合而包含額外的頭文件。詳言之,一個頭文件要有1.2. #define 保護,統統包含它所需要的其它頭文件,也不要求定義任何特別 symbols.

不過有一個例外,即一個文件并不是 self-contained 的,而是作為文本插入到代碼某處?;蛘?,文件內容實際上是其它頭文件的特定平臺(platform-specific)擴展部分。這些文件就要用.inc文件擴展名。

如果.h文件聲明了一個模板或內聯函數,同時也在該文件加以定義。凡是有用到這些的.cc文件,就得統統包含該頭文件,否則程序可能會在構建中鏈接失敗。不要把這些定義放到分離的-inl.h文件里(譯者注:過去該規范曾提倡把定義放到 -inl.h 里過)。

有個例外:如果某函數模板為所有相關模板參數顯式實例化,或本身就是某類的一個私有成員,那么它就只能定義在實例化該模板的.cc文件里。

1.2. #define 保護

Tip

所有頭文件都應該使用#define來防止頭文件被多重包含, 命名格式當是:___H_.

為保證唯一性, 頭文件的命名應該基于所在項目源代碼樹的全路徑. 例如, 項目foo中的頭文件foo/src/bar/baz.h可按如下方式保護:

#ifndef FOO_BAR_BAZ_H_#define FOO_BAR_BAZ_H_...#endif // FOO_BAR_BAZ_H_

1.3. 前置聲明

Tip

盡可能地避免使用前置聲明。使用#include包含需要的頭文件即可。

定義:

所謂「前置聲明」(forward declaration)是類、函數和模板的純粹聲明,沒伴隨著其定義.

優點:

前置聲明能夠節省編譯時間,多余的#include會迫使編譯器展開更多的文件,處理更多的輸入。

前置聲明能夠節省不必要的重新編譯的時間。#include使代碼因為頭文件中無關的改動而被重新編譯多次。

缺點:

前置聲明隱藏了依賴關系,頭文件改動時,用戶的代碼會跳過必要的重新編譯過程。

前置聲明可能會被庫的后續更改所破壞。前置聲明函數或模板有時會妨礙頭文件開發者變動其 API. 例如擴大形參類型,加個自帶默認參數的模板形參等等。

前置聲明來自命名空間std::的 symbol 時,其行為未定義。

很難判斷什么時候該用前置聲明,什么時候該用#include。極端情況下,用前置聲明代替includes甚至都會暗暗地改變代碼的含義:

// b.h:struct B {};struct D : B {}// good_user.cc:#include "b.h"void f(B*);void f(void*);void test(D* x) { f(x); } // calls f(B*)

如果#include被B和D的前置聲明替代,test()就會調用f(void*).

前置聲明了不少來自頭文件的 symbol 時,就會比單單一行的include冗長。

僅僅為了能前置聲明而重構代碼(比如用指針成員代替對象成員)會使代碼變得更慢更復雜.

結論:

盡量避免前置聲明那些定義在其他項目中的實體.

函數:總是使用#include.

類模板:優先使用#include.

至于什么時候包含頭文件,參見1.5. #include 的路徑及順序。

1.4. 內聯函數

Tip

只有當函數只有 10 行甚至更少時才將其定義為內聯函數.

定義:

當函數被聲明為內聯函數之后, 編譯器會將其內聯展開, 而不是按通常的函數調用機制進行調用.

優點:

只要內聯的函數體較小, 內聯該函數可以令目標代碼更加高效. 對于存取函數以及其它函數體比較短, 性能關鍵的函數, 鼓勵使用內聯.

缺點:

濫用內聯將導致程序變得更慢. 內聯可能使目標代碼量或增或減, 這取決于內聯函數的大小. 內聯非常短小的存取函數通常會減少代碼大小, 但內聯一個相當大的函數將戲劇性的增加代碼大小. 現代處理器由于更好的利用了指令緩存, 小巧的代碼往往執行更快。

結論:

一個較為合理的經驗準則是, 不要內聯超過 10 行的函數. 謹慎對待析構函數, 析構函數往往比其表面看起來要更長, 因為有隱含的成員和基類析構函數被調用!

另一個實用的經驗準則: 內聯那些包含循環或switch語句的函數常常是得不償失 (除非在大多數情況下, 這些循環或switch語句從不被執行).

有些函數即使聲明為內聯的也不一定會被編譯器內聯, 這點很重要; 比如虛函數和遞歸函數就不會被正常內聯. 通常, 遞歸函數不應該聲明成內聯函數.(YuleFox 注: 遞歸調用堆棧的展開并不像循環那么簡單, 比如遞歸層數在編譯時可能是未知的, 大多數編譯器都不支持內聯遞歸函數). 虛函數內聯的主要原因則是想把它的函數體放在類定義內, 為了圖個方便, 抑或是當作文檔描述其行為, 比如精短的存取函數.

1.5.#include的路徑及順序

Tip

使用標準的頭文件包含順序可增強可讀性, 避免隱藏依賴: 相關頭文件, C 庫, C++ 庫, 其他庫的.h, 本項目內的.h.

項目內頭文件應按照項目源代碼目錄樹結構排列, 避免使用 UNIX 特殊的快捷目錄.(當前目錄) 或..(上級目錄). 例如,google-awesome-project/src/base/logging.h應該按如下方式包含:

#include "base/logging.h"

又如,dir/foo.cc或dir/foo_test.cc的主要作用是實現或測試dir2/foo2.h的功能,foo.cc中包含頭文件的次序如下:

dir2/foo2.h(優先位置, 詳情如下)

C 系統文件

C++ 系統文件

其他庫的.h文件

本項目內.h文件

這種優先的順序排序保證當dir2/foo2.h遺漏某些必要的庫時,dir/foo.cc或dir/foo_test.cc的構建會立刻中止。因此這一條規則保證維護這些文件的人們首先看到構建中止的消息而不是維護其他包的人們。

dir/foo.cc和dir2/foo2.h通常位于同一目錄下 (如base/basictypes_unittest.cc和base/basictypes.h), 但也可以放在不同目錄下.

按字母順序分別對每種類型的頭文件進行二次排序是不錯的主意。注意較老的代碼可不符合這條規則,要在方便的時候改正它們。

您所依賴的符號 (symbols) 被哪些頭文件所定義,您就應該包含(include)哪些頭文件,前置聲明(forward declarations) 情況除外。比如您要用到bar.h中的某個符號, 哪怕您所包含的foo.h已經包含了bar.h, 也照樣得包含bar.h, 除非foo.h有明確說明它會自動向您提供bar.h中的 symbol. 不過,凡是 cc 文件所對應的「相關頭文件」已經包含的,就不用再重復包含進其 cc 文件里面了,就像foo.cc只包含foo.h就夠了,不用再管后者所包含的其它內容。

舉例來說,google-awesome-project/src/foo/internal/fooserver.cc的包含次序如下:

#include "foo/public/fooserver.h" // 優先位置#include #include #include #include #include "base/basictypes.h"#include "base/commandlineflags.h"#include "foo/public/bar.h"

例外:

有時,平臺特定(system-specific)代碼需要條件編譯(conditional includes),這些代碼可以放到其它 includes 之后。當然,您的平臺特定代碼也要夠簡練且獨立,比如:

#include "foo/public/fooserver.h"#include "base/port.h" // For LANG_CXX11.#ifdef LANG_CXX11#include #endif // LANG_CXX11

譯者 (YuleFox) 筆記

避免多重包含是學編程時最基本的要求;

前置聲明是為了降低編譯依賴,防止修改一個頭文件引發多米諾效應;

內聯函數的合理使用可提高代碼執行效率;

-inl.h可提高代碼可讀性 (一般用不到吧:D);

標準化函數參數順序可以提高可讀性和易維護性 (對函數參數的堆??臻g有輕微影響, 我以前大多是相同類型放在一起);

包含文件的名稱使用.和..雖然方便卻易混亂, 使用比較完整的項目路徑看上去很清晰, 很條理, 包含文件的次序除了美觀之外, 最重要的是可以減少隱藏依賴, 使每個頭文件在 “最需要編譯” (對應源文件處 :D) 的地方編譯, 有人提出庫文件放在最后, 這樣出錯先是項目內的文件, 頭文件都放在對應源文件的最前面, 這一點足以保證內部錯誤的及時發現了.

譯者(acgtyrant)筆記

原來還真有項目用#includes來插入文本,且其文件擴展名.inc看上去也很科學。

Google 已經不再提倡-inl.h用法。

注意,前置聲明的類是不完全類型(incomplete type),我們只能定義指向該類型的指針或引用,或者聲明(但不能定義)以不完全類型作為參數或者返回類型的函數。畢竟編譯器不知道不完全類型的定義,我們不能創建其類的任何對象,也不能聲明成類內部的數據成員。

類內部的函數一般會自動內聯。所以某函數一旦不需要內聯,其定義就不要再放在頭文件里,而是放到對應的.cc文件里。這樣可以保持頭文件的類相當精煉,也很好地貫徹了聲明與定義分離的原則。

在#include中插入空行以分割相關頭文件, C 庫, C++ 庫, 其他庫的.h和本項目內的.h是個好習慣。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Google
    +關注

    關注

    5

    文章

    1714

    瀏覽量

    56797
  • 編程
    +關注

    關注

    88

    文章

    3441

    瀏覽量

    92443
  • C++
    C++
    +關注

    關注

    21

    文章

    2066

    瀏覽量

    72903

原文標題:Google C++ 編程規范 - 1

文章出處:【微信號:C_Expert,微信公眾號:C語言專家集中營】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    MATLAB 編程風格指南

    thebeginning.”(良好的寫作規范的程序比糟糕的寫作規范的要好,因為他們具有較少的錯誤、易于調試與修改,因此,從開始就考慮風格是很重要的)。本指南列舉的MATLAB 代碼編寫的建議在
    發表于 09-22 16:19

    Google C++編程指南

    Google C++編程指南目標:增強代碼致性,創建通用的、必需的習慣用語和模式可以使代碼更加容易理解C++是門包含大量高級特性的巨型語
    發表于 11-29 09:15

    討論編程風格與技巧是怎樣提高設計性能的?

    討論編程風格與技巧是怎樣提高設計性能的?
    發表于 05-07 06:31

    MATLAB編程風格指南

    有關 MATLAB代碼的建議通常強調的是效率,譬如說有關“不要用循環”等的建議,本指南與之不同。本指南主要考慮的是代碼(格式)的正確性、清晰性與通用性。本指南的目的在
    發表于 07-18 10:54 ?0次下載

    linux內核C語言的編程風格

    linux 內核C語言的編程風格
    發表于 09-26 14:22 ?0次下載

    avr單片機c語言編程風格介紹

    摘要:作為一個初學者如何具有良好的程序設計風格呢?下面小編將以avr單片機介紹它的c語言編程風格。
    發表于 12-10 10:08 ?5864次閱讀
    avr單片機c語言<b class='flag-5'>編程</b><b class='flag-5'>風格</b>介紹

    Google編程風格指南(二)

    鼓勵在 .cc 文件內使用匿名命名空間或 static 聲明. 使用具名的命名空間時, 其名稱可基于項目名或相對路徑. 禁止使用 using 指示(using-directive)。禁止使用內聯命名空間(inline namespace)。
    的頭像 發表于 09-27 18:01 ?2387次閱讀

    Google編程風格指南(三)

    C/C++ 中的函數參數或者是函數的輸入, 或者是函數的輸出, 或兼而有之. 輸入參數通常是值參或 const 引用, 輸出參數或輸入/輸出參數則一般為非 const 指針. 在排列參數順序時, 將所有的輸入參數置于輸出參數之前. 特別要注意, 在加入新參數時不要因為它們是新參數就置于參數列表最后, 而是仍然要按照前述的規則, 即將新的輸入參數也置于輸出參數之前.
    的頭像 發表于 09-27 18:06 ?2351次閱讀

    Google編程風格指南(四)

    用于定義移動構造函數 (使用類的右值引用進行構造的函數) 使得移動一個值而非拷貝之成為可能. 例如, 如果 v1 是一個 vector, 則 auto v2(std::move(v1)) 將很可能不再進行大量的數據復制而只是簡單地進行指針操作, 在某些情況下這將帶來大幅度的性能提升.
    的頭像 發表于 09-27 18:08 ?2648次閱讀

    Google編程風格指南(五)

    所有具有靜態存儲類型的變量 (例如靜態變量或全局變量, 參見 存儲類型) 都應當以此方式命名. 對于其他存儲類型的變量, 如自動變量等, 這條規則是可選的. 如果不采用這條規則, 就按照一般的變量命名規則.
    的頭像 發表于 09-27 18:15 ?2274次閱讀

    Google編程風格指南(六)

    即使是英文, 也不應將用戶界面的文本硬編碼到源代碼中, 因此非 ASCII 字符應當很少被用到. 特殊情況下可以適當包含此類字符. 例如, 代碼分析外部數據文件時, 可以適當硬編碼數據文件中作為分隔符的非 ASCII 字符串; 更常見的是 (不需要本地化的) 單元測試代碼可能包含非 ASCII 字符串. 此類情況下, 應使用 UTF-8 編碼, 因為很多工具都可以理解和處理 UTF-8 編碼.
    的頭像 發表于 09-27 18:18 ?2530次閱讀

    Google C++編程風格指南PDF版免費下載

    Google的項目大多使用C++開發。每一個C++程序員也都知道, C++具有很多強大的語言特性,但這種強大不可避免的導致它的復雜,而復雜性會使得代碼更容易出現bug.難于閱讀和維護。
    發表于 03-06 08:00 ?0次下載
    <b class='flag-5'>Google</b> C++<b class='flag-5'>編程</b><b class='flag-5'>風格</b><b class='flag-5'>指南</b>PDF版免費下載

    Verilog HIDL的RTL設計風格指南資源下載

    Verilog HIDL的RTL設計風格指南資源下載
    發表于 04-13 10:09 ?9次下載

    西門子S7-1200和S7-1500編程風格指南

    西門子S7-1200和S7-1500編程風格指南分享
    發表于 08-17 17:30 ?17次下載

    Google Python代碼風格指南

    1 背景 Python是谷歌主要使用的動態語言,本風格指導列舉了使用Python編程時應該做和不該做的事項(dos nothing on first line # 縮進4個空格,首行括號后無內容
    的頭像 發表于 11-03 10:20 ?2776次閱讀
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>