Google C++ 代码样式指南

代码规范对于一个项目、一个团队乃至一个公司是十分重要的要求。

国内有阿里发布的的《Java 开发手册》,但是Java只是众多流行语言中的一个,很多语言由于语法规则、编译过程、内存管理等与Java存在较大的差异。本文通过翻译Google C++ Style Guide来展示C++编码过程中需要注意的规范。

背景

C ++是许多Google开源项目使用的主要开发语言之一。每个C ++程序员都知道,该语言具有许多强大的功能,但是这种功能带来了复杂性,从而使代码更容易出现错误,并且难以阅读和维护。

本指南的目的是通过详细描述编写C ++代码的注意事项来管理这种复杂性。这些规则的存在是为了使代码库易于管理,同时仍然允许编码人员有效地使用C ++语言功能。

样式(也称为可读性)是我们用来控制C ++代码的约定。术语“样式”有点用词不当,因为这些约定不仅涵盖源文件格式,还涉及更多内容。

Google开发的大多数开源项目都符合本指南的要求。

请注意,本指南不是C ++教程:我们假定读者熟悉该语言。

本文的目的

为什么有这篇文章

我们认为本指南应达到一些核心目标,这些就是所有规则背后的根本原因。通过突出这些想法,我们希望能够进行讨论,并使我们更广泛的社区更清楚为何制定了规则以及为何做出了特定的决定。如果您了解每个规则所服务的目标,则应该让所有人(在某些情况下可以放弃)更清楚地知道每个规则,以及在指南中更改规则所需的论点或替代方式。

  • 样式规则应发挥作用
    样式规则的好处必须足够大,足以证明要求我们所有的工程师记住它。收益是相对于没有该规则我们将获得的代码库进行衡量的,因此,如果人们无论如何都不愿意这样做,那么针对非常有害实践的规则可能仍然会产生很小的收益。该原则主要解释我们没有的规则,而不是我们所遵循的规则:例如,它goto违反了以下许多原则,但是已经很少消失了,因此样式指南不再讨论。
  • 针对读者而非作家进行优化
    我们的代码库(以及提交给它的大多数单个组件)预计将持续相当长的一段时间。结果,与编写代码相比,将花费更多的时间阅读我们的大多数代码。我们明确选择针对普通软件工程师在我们的代码库中读取,维护和调试代码的体验进行优化,而不是在编写所述代码时就轻松了。“为读者留下痕迹”是该原理的一个特别常见的子要点:当一段代码中发生了令人惊讶或异常的事情时(例如,指针所有权的转移),此时,给读者留下了文本提示使用非常有价值(std::unique_ptr 在呼叫站点明确演示了所有权转移)。
  • 与现有代码保持一致
    在我们的代码库中一致地使用一种样式,使我们可以专注于其他(更重要的)问题。一致性还可以实现自动化:格式化代码或调整代码的工具#include只有在代码与工具的期望一致时才能正常工作。在许多情况下,归因于“保持一致”的规则可以归结为“仅选择一个就不再担心”。在这些问题上允许灵活性的潜在价值被人们为之争论的成本所抵消。
  • 在适当的时候与更广泛的C ++社区保持一致
    与其他组织使用C ++的方式保持一致具有价值,其原因与我们代码库中的保持一致相同。如果C ++标准中的某个功能解决了问题,或者某个惯用语已广为人知并被接受,那么这就是使用它的理由。但是,有时标准功能和习惯用法有缺陷,或者只是在设计时就没有考虑我们的代码库的需求。在这种情况下(如下所述),应该限制或禁止标准功能。在某些情况下,出于感知上的优势或价值不足以将代码库过渡到标准接口,我们更喜欢使用本地库或第三方库,而不是C ++标准中定义的库。
  • 避免令人惊讶或危险的构造
    C ++具有比人们一眼就能想到的功能更令人惊讶或危险的功能。一些样式指南限制到位,以防止陷入这些陷阱。对于这样的限制,放弃样式指南的门槛很高,因为放弃这样的规则通常会直接损害程序的正确性。
  • 避免使用普通C ++程序员会发现棘手或难以维护的结构
    由于C ++引入代码的复杂性,因此C ++具有通常可能不合适的功能。在广泛使用的代码中,使用更具技巧性的语言构造可能会更容易接受,因为更复杂的实现所带来的任何好处都会因使用而倍增,并且在使用复杂的语言部分时无需再次付出理解复杂性的代价。代码库。如有疑问,可通过询问您的项目负责人寻求豁免此类规则。这对于我们的代码库特别重要,因为代码所有权和团队成员关系会随着时间而变化:即使目前使用某段代码的每个人都可以理解,但仍不能保证这种理解会持续几年。
  • 注意我们的规模
    拥有100+百万行代码库和数千名工程师的代码库,对于一位工程师来说,一些错误和简化可能会使许多人付出高昂的代价。例如,避免污染全局名称空间尤为重要:跨亿万行的代码库中的名称冲突很难处理,如果每个人都将其放入全局名称空间,则很难避免。
  • 必要时考虑进行优化
    性能优化有时可能是必要且适当的,即使它们与本文档的其他原则冲突也是如此。

通过这种方式,我们专门引用了整个Google C ++社区的既定惯例,而不仅仅是您个人或团队的个人喜好。持怀疑态度,不愿使用聪明或不寻常的构造:没有禁止就等于进行许可。使用您的判断,如果不确定,请不要犹豫,要求您的项目负责人获得其他意见。

本文适用于C++ 17 并不完全适配C++ 2X

头文件

通常,每个.cc文件都应具有关联的.h文件。有一些常见的例外,例如单元测试和.cc仅包含main()函数的小文件。

正确使用头文件会对代码的可读性,大小和性能产生巨大影响。

下列规则将指导您解决使用头文件的各种陷阱。

独立的头文件

头文件应该是能进行独立的自我编译,并以结尾.h。打算包含的非标头文件应结尾.inc并应谨慎使用。

所有头文件都应该是独立的。用户和重构工具不必遵守特殊条件即可包含标题。具体来说,标头应具有标头防护,并包括它需要的所有其他标头。

最好将模板和内联函数的定义与其声明放在同一文件中。这些构造的定义必须包含在.cc使用它们的每个文件中,否则程序可能无法在某些构造配置中链接。如果声明和定义在不同的文件中,则前者应可传递地包括后者。请勿将这些定义移动到单独包含的头文件(-inl.h)中;过去这种做法很普遍,但现在不再允许。

作为例外,允许在一个唯一的.cc实例化模板的文件中定义为所有相关的模板参数集显式实例化的模板,或者是类的私有实现细节。

在极少数情况下,设计为包含的文件不是自包含的。通常将它们包含在不寻常的位置,例如另一个文件的中间。他们可能不使用标题保护,也可能不包括其先决条件。用.inc 扩展名命名此类文件。谨慎使用,并尽可能使用独立的标头。

#define 保护

所有头文件都应具有#define防护措施,以防止多次包含。符号名称的格式应为 。
<PROJECT>_<PATH>_<FILE>_H_
为了保证唯一性,它们应基于项目源代码树中的完整路径。例如,foo/src/bar/baz.h项目中的文件foo应具有以下防护:

#ifndef FOO_BAR_BAZ_H_
#定义FOO_BAR_BAZ_H_

...

#endif // FOO_BAR_BAZ_H_

前置声明

猜你喜欢

转载自blog.csdn.net/u013741019/article/details/107401137