这是一套现代C++(目前为C++20和C++17)的核心准则,同时考虑到未来可能的增强和ISO技术规范(TS)。目的是帮助C++程序员编写更简单、更高效、更易于维护的代码。
介绍摘要:
In.target:目标读者群
所有C++程序员。这包括可能考虑C的程序员。
In.目标:目标
本文档的目的是帮助开发人员采用现代C++(目前为C++20和C++17),并实现跨代码库更统一的风格。
我们不会错觉这些规则中的每一个都可以有效地应用于每个代码库。升级旧系统很难。然而,我们确实认为,使用规则的程序比不使用规则的程序更容易出错,也更容易维护。通常,规则还会导致更快/更容易的初始开发。据我们所知,这些规则导致代码的性能与更古老、更传统的技术一样好或更好;它们旨在遵循零开销原则(“您不使用的东西,您不付费”或“当您适当使用抽象机制时,您至少会获得与使用较低级别的语言结构手工编码一样的良好性能”)。考虑这些规则对新代码的理想,在处理旧代码时可以利用的机会,并尝试尽可能接近这些理想。记住:
In.0:不要惊慌!
花点时间了解指南规则对您的计划的影响。
这些指南是根据“超集子集”原则(Stroustrup05)设计的。它们不只是定义要使用的C++的子集(为了可靠性、安全性、性能或其他)。相反,他们强烈建议使用一些简单的“扩展”(库组件),使C++最容易出错的功能变得多余,以便禁止它们(在我们的一套规则中)。
这些规则强调静态类型安全和资源安全。因此,他们强调范围检查、避免取消引用nullptr
、避免悬垂的指针以及系统使用异常的可能性(通过RAII)。一方面为了实现这一点,另一方面为了尽量减少作为错误来源的晦涩代码,这些规则还强调简单性和隐藏在指定良好的接口后面的必要复杂性。
许多规则都是规范性的。我们对简单地声明“不要那样做!”的规则感到不舒服!没有提供替代方案。其结果之一是,一些规则只能得到启发式检查的支持,而不是精确和可机械验证的检查。其他规则阐明了一般原则。对于这些更通用的规则,更详细和具体的规则提供了部分检查。
这些指南涉及C++的核心及其使用。我们预计大多数大型组织、特定应用领域甚至大型项目都需要进一步的规则、可能的进一步限制和进一步的图书馆支持。例如,硬实时程序员通常不能自由使用免费存储(动态内存),并且在选择库时会受到限制。我们鼓励制定更具体的规则,如这些核心准则的增编。构建您理想的小型基础库并使用它,而不是降低您的编程水平以美化的汇编代码。
这些规则旨在允许逐步采用。
一些规则旨在增加各种形式的安全,而另一些规则旨在减少事故的可能性,许多规则同时这样做。旨在预防事故的指南通常禁止完全合法的C++。然而,当有两种表达想法的方式,一种表明自己是共同的错误来源,另一种不是时,我们试图引导程序员走向后者。
In.not:非目标
这些规则不打算最小化或正交。特别是,一般规则可能很简单,但不可执行。此外,通常很难理解一般规则的含义。更专业的规则通常更容易理解和执行,但如果没有一般规则,它们只是一长串特殊情况。我们提供旨在帮助新手的规则以及支持专家使用的规则。有些规则可以完全执行,但另一些则基于启发式。
这些规则不应该像书一样连续阅读。您可以使用链接浏览它们。然而,它们的主要用途是成为工具的目标。也就是说,工具会寻找违规行为,该工具会返回违反规则的链接。然后,规则提供了原因、违规的潜在后果示例以及建议的补救措施。
这些指南无意替代C++的教程处理。如果您需要一定水平经验的教程,请参阅参考资料。
这不是关于如何将旧C++代码转换为更现代代码的指南。它旨在以具体的方式阐明新代码的想法。然而,请参阅现代化部分,了解现代化/振兴/升级的一些可能方法。重要的是,这些规则支持逐步采用:同时完全转换大型代码库通常是不可行的。
这些指南并不是每个语言技术细节都完整或准确。有关语言定义问题的最后一句话,包括一般规则和每个功能的每个例外,请参阅ISO C++标准。
这些规则无意强迫你用贫穷的C++子集编写。它们强调并不意味着定义C++的类似Java的子集。它们不是为了定义一种“一种真正的C++”语言。我们重视表现力和不妥协的表现。
这些规则不是价值中立的。它们旨在使代码比大多数现有的C++代码更简单、更正确/更安全,而不会损失性能。它们旨在抑制与错误、虚假复杂性和性能差相关的完美有效的C++代码。
这些规则并不精确到人(或机器)可以不假思索地遵循它们的程度。执行部分试图如此,但我们宁愿留下一个规则或定义有点模糊和开放解释,而不是指定一些准确和错误的东西。有时,精确性只会随着时间和经验而来。设计(还)不是数学的一种形式。
规则并不完美。一条规则可以通过禁止在特定情况下有用的东西来造成伤害。规则如果不禁止在特定情况下导致严重错误的东西,可能会造成伤害。一条规则通过模糊、模棱两可、不可执行或使问题的每个解决方案都可能造成很多伤害。完全符合“无害”标准是不可能的。相反,我们的目标是不那么雄心勃勃:“为大多数程序员做最大的好事”;如果你不能接受一条规则,反对它,忽略它,但不要淡化它,直到它变得毫无意义。此外,建议改进。
In.force:执行
对于大型代码库来说,没有执行的规则是无法管理的。只有一小部分薄弱的规则或特定的用户社区才能执行所有规则。
- 但我们希望有很多规则,我们想要每个人都可以使用的规则。
- 但不同的人有不同的需求。
- 但人们不喜欢读很多规则。
- 但人们不记得很多规则。
因此,我们需要子集来满足各种需求。
- 但任意的子设置会导致混乱。
我们想要帮助许多人的指导方针,使代码更加统一,并强烈鼓励人们将代码现代化。我们希望鼓励最佳实践,而不是将所有留给个人选择和管理压力。理想情况下,使用所有规则;这会带来最大的好处。
这增加了相当多的困境。我们试图使用工具解决这些问题。每条规则都有一个执行部分,列出了执行的想法。执行可以通过代码审查、静态分析、编译器或运行时检查来完成。只要有可能,我们更喜欢“机械”检查(人类缓慢、不准确、容易无聊)和静态检查。只有在没有替代方案的地方才建议很少进行运行时检查;我们不想引入“分布式膨胀”。在适当的情况下,我们用相关规则组(称为“配置文件”)的名称标记规则(在执行部分中)。规则可以是多个配置文件的一部分,也可以没有。首先,我们有一些与共同需求(愿望、理想)相对应的配置文件:
- 类型:无类型违规(通过铸造、工会或varargs将
T
重新解释为U
) - 边界:无边界违规(访问超出阵列范围)
- 生命周期:没有泄漏(未能
delete
或多次delete
),也无法访问无效对象(使用悬空引用取消引用nullptr
)。
这些配置文件旨在供工具使用,但也为人类读者提供帮助。我们不会将我们在执法部分的评论局限于我们知道如何执行的事情;一些评论只是可能激励一些工具建设者的愿望。
实现这些规则的工具应尊重以下语法来明确压制规则:
[[gsl::suppress(tag)]]
并可选地带有消息(遵循通常的C++11标准属性语法):
[[gsl::suppress(tag, justification: "message")]]
地点
-
tag
是出现执行规则的项目的锚名(例如,对于C.134,它是“Rh-public”),配置文件规则组(“类型”、“边界”或“生命周期”)的名称,或配置文件中的特定规则(类型.4或边界。2) -
"message"
是字符串的字面意思
In.struct:本文档的结构
每条规则(指南、建议)可以有几个部分:
- 规则本身——例如,没有裸体
new
- 规则参考编号-例如,C.7(与类相关的第7条规则)。由于主要部分不是固有的顺序,我们使用字母作为规则引用“数字”的第一部分。我们在编号中留下空白,以便在添加或删除规则时尽量减少“中断”。
- 原因(理性)——因为程序员发现很难遵循他们不理解的规则
- 例子——因为规则很难抽象理解;可以是积极的,也可以是消极的
- 替代方案-“不要这样做”规则
- 例外-我们更喜欢简单的一般规则。然而,许多规则广泛适用,但不是普遍适用,因此必须列出例外情况
- 执行-关于如何“机械地”检查规则的想法
- 另见-参考相关规则和/或进一步讨论(在本文件或其他地方)
- 注释(评论)-需要说的不符合其他分类的东西
- 讨论-参考放在主要规则列表之外的更广泛的理由和/或示例
有些规则很难机械检查,但它们都符合专家程序员可以毫不费力地发现许多违规行为的最低标准。我们希望“机械”工具将随着时间的推移而改进,以近似此类专家程序员注意到的内容。此外,我们假设这些规则将随着时间的推移而完善,使其更加精确和可检查。
规则旨在简单,而不是仔细措辞以提及每个替代方案和特殊情况。此类信息可在替代段落和讨论部分找到。如果您不理解或不同意该规则,请访问其讨论。如果您觉得讨论缺失或不完整,请输入一个问题来解释您的担忧,并可能进行相应的公关。
写示例是为了说明规则。
- 示例不是为了生产质量或涵盖所有教程维度。例如,许多示例是语言技术性的,并使用
f
、base
和x
等名称。 - 我们努力确保“好”的例子遵循核心准则。
- 评论通常说明了在“真实代码”中不必要的和/或分散注意力的规则。
- 我们假设了解标准图书馆。例如,我们使用普通
vector
而不是std::vector
。
这不是一本语言手册。它旨在对技术细节或现有代码指南有帮助,而不是完整、完全准确。推荐的信息来源可以在参考资料中找到。
In.sec:主要部分
- 在:简介
- P:哲学
- I:接口
- F:功能
- C:班级和班级层次结构
- 枚举:枚举
- R:资源管理
- ES:表达和语句
- 每:性能
- CP:并发和并行性
- E:错误处理
- 缺点:常数和不变性
- T:模板和通用编程
- CPL:C式编程
- SF:源文件
- SL:标准图书馆
支持部分:
- A:建筑理念
- NR:非规则和神话
- RF:参考资料
- 优点:配置文件
- GSL:指南支持图书馆
- NL:命名和布局建议
- 常见问题:常见问题的答案
- 附录A:图书馆
- 附录B:代码现代化
- 附录C:讨论
- 附录D:支持工具
- 词汇
- 待办事项:非机密的原始规则
这些部分不是正交的。
每个部分(例如“哲学”的“P”)和每个小节(例如“Class Hier”(OOP)的“C.hier”)都有一个缩写,便于搜索和参考。主要部分的缩写也用于规则编号(例如,“C.11”表示“使具体类型规则”)。