背景
C++ 是 Google 许多开源项目使用的主要开发语言之一。正如每个 C++ 程序员所知,这门语言有许多强大的特性,但这种强大也带来了复杂性,而复杂性反过来会使代码更容易出现错误(Bug),也更难以阅读和维护。
本指南的目标是通过详细描述编写 C++ 代码的注意事项来管理这种复杂性。这些规则的存在是为了在允许程序员高效使用 C++ 语言特性的同时,保持代码库的可维护性。
风格(Style),也称为可读性(Readability),是我们对管理 C++ 代码的约定的称呼。“风格”这个术语有些名不副实,因为这些约定涵盖的内容远不止源文件格式化。
Google 开发的大多数开源项目都遵循本指南中的要求。
请注意,本指南不是 C++ 教程:我们假设读者已经熟悉这门语言。
风格指南的目标
为什么我们需要这份文档?
我们认为本指南应该服务于几个核心目标。这些是所有具体规则背后的根本原因。通过将这些理念提到前台,我们希望能够为讨论提供基础,并让更广泛的社区更清楚地了解这些规则存在的原因以及为什么做出了特定的决策。如果你理解每条规则所服务的目标,那么对每个人来说,何时可以豁免规则(有些可以),以及需要什么样的论据或替代方案才能更改指南中的规则,都会更加清楚。
我们目前认为风格指南的目标如下:
风格规则应该物有所值
风格规则的收益必须足够大,以证明要求所有工程师记住它是合理的。收益是相对于没有该规则时我们会得到的代码库来衡量的,因此即使一条规则针对的是一种非常有害的实践,如果人们本来就不太可能这么做,那么它的收益仍然很小。这一原则主要解释了我们没有制定的规则,而不是我们已有的规则:例如,goto
违反了以下许多原则,但它已经极其罕见,所以风格指南不讨论它。
为读者而非作者优化
我们的代码库(以及提交到其中的大多数单独组件)预计将持续存在相当长的时间。因此,阅读我们大部分代码所花费的时间将比编写它更多。我们明确选择为在代码库中阅读、维护和调试代码的普通软件工程师的体验进行优化,而不是为编写代码时的便利性优化。“为读者留下线索”是这一原则中一个特别常见的子要点:当代码片段中发生了令人惊讶或不寻常的事情时(例如,指针所有权的转移),在使用点为读者留下文字提示是很有价值的(std::unique_ptr
在调用点明确地展示了所有权转移)。
与现有代码保持一致
在整个代码库中一致地使用一种风格可以让我们专注于其他(更重要的)问题。一致性还允许自动化:格式化代码或调整
#include
的工具只有在代码符合工具的预期时才能正常工作。在许多情况下,归因于”保持一致”的规则归结为”选择一个然后不要再为此烦恼”;在这些方面允许灵活性的潜在价值被人们为此争论的成本所抵消。然而,一致性是有限度的;当没有明确的技术论据,也没有长期方向时,它是一个好的决胜因素。它在局部(每个文件,或一组紧密相关的接口)更为适用。一致性通常不应被用作以旧风格做事的理由,而不考虑新风格的好处,或代码库随时间向更新风格收敛的趋势。
在适当的时候与更广泛的 C++ 社区保持一致
与其他组织使用 C++
的方式保持一致,其价值与在我们代码库内保持一致的原因相同。如果 C++
标准中的某个特性解决了一个问题,或者某种惯用法被广泛了解和接受,那就是使用它的一个理由。然而,有时标准特性和惯用法是有缺陷的,或者在设计时没有考虑到我们代码库的需求。在这些情况下(如下所述),限制或禁止标准特性是合适的。在某些情况下,我们更倾向于使用自研或第三方库而不是
C++
标准中定义的库,这可能是出于认为前者更优越,或者将代码库迁移到标准接口的价值不足。
避免令人惊讶或危险的构造
C++
有一些特性比乍看之下更令人惊讶或更危险。一些风格指南的限制是为了防止落入这些陷阱。对于此类限制的风格指南豁免有很高的门槛,因为豁免此类规则通常直接冒着损害程序正确性的风险。
避免我们的普通 C++ 程序员会觉得棘手或难以维护的构造
C++
有一些特性可能因为它们给代码引入的复杂性而不适合普遍使用。在被广泛使用的代码中,使用更巧妙的语言构造可能更容易被接受,因为更复杂实现的好处会被广泛的使用所放大,而理解复杂性的成本在处理代码库的新部分时不需要再次支付。如果有疑问,可以通过询问项目负责人来寻求此类规则的豁免。这对于我们的代码库尤其重要,因为代码所有权和团队成员会随时间变化:即使目前所有使用某段代码的人都理解它,这种理解也不能保证在几年后仍然成立。
注意我们的规模
拥有超过 1
亿行代码和数千名工程师的代码库,一个工程师的某些错误和简化可能会对许多人造成代价。例如,避免污染全局命名空间(Namespace)尤为重要:如果每个人都将东西放入全局命名空间,那么在数亿行的代码库中,名称冲突将难以处理且难以避免。
必要时向优化让步
性能优化有时是必要的和适当的,即使它们与本文档的其他原则相冲突。
本文档的意图是在合理限制的前提下提供最大程度的指导。一如既往,应以常识和良好的品味为准。这里我们具体指的是整个 Google C++ 社区的既定约定,而不仅仅是你个人的偏好或你团队的偏好。对巧妙或不寻常的构造保持怀疑和谨慎:没有禁止并不等同于许可。运用你的判断力,如果你不确定,请不要犹豫,向你的项目负责人寻求额外的意见。