C++ 使用规范

解释

从 Godot 4.0 开始,代码库中所使用的 C++ 标准是 C++17 的子集。现代 C++ 带来了许多机会,让我们能够编写更快、更易读的代码,但我们选择将我们对 C++ 的使用限制在一个子集中,原因有这么几点:

  • 易于使用在线编辑器审核代码。这是因为引擎的贡献者在审核代码时并不总是可以使用完整的 IDE。

  • 易于让新手贡献者掌握代码(他们可能不是专业的 C++ 程序员)。Godot 的代码库是公认的易于学习,我们希望继续保持。

要让你的拉取请求被合并,就需要遵守这里描述的 C++ 使用规范。当然,在你自己的 C++ 模块或 GDNative 脚本中是可以使用此处禁止的特性的。

备注

在 Godot 4.0 之前的版本中,代码库所使用的 C++ 标准曾是 C++03,外加一些 C++14 扩展。如果你是在为 3.x 分支提交拉取请求而不是 master,就不能使用 C++17 的特性。请确保你的代码能够使用 C++14 编译器构建。

以下规范并不适用于第三方依赖,虽然我们一般倾向于使用小型的库而不是大型的解决方案。另请参阅 引擎贡献者的最佳实践

参见

格式化规范请参阅 代码风格规范

禁用的特性

未在下方列出的特性都是允许的。鼓励尽可能使用 constexpr 变量和 nullptr 等特性。不过请您在使用现代 C++ 特性时保持保守。使用时应当为实际的目的服务,例如提升代码可读性或性能。

标准模板库

我们不允许使用 STL,因为 Godot 提供了自有的数据类型(及其他工具)。详情请参阅 为什么 Godot 不使用 STL(标准模板库)?

这意味着拉取请求中不应该使用 std::stringstd::vector 等工具。请使用如下所述的 Godot 数据类型代替:

  • 使用 String 代替 std::string

  • 使用 Vector 代替 std::vector。某些情况下也可以用 LocalVector 代替(请先咨询核心开发者)。

  • 使用 Array 代替 std::array

备注

Godot 还有一个 List 数据类型(是个链表)。虽然 List 在代码库中有所使用,但一般性能都比 Vector 和 Array 等数据类型要差。因此,除非必要,否则应该避免在新代码中使用 List。

auto 关键字

请勿使用 auto 关键字进行类型推导。虽然可以避免重复,但也可能导致令人费解的代码:

  1. // Not so confusing...
  2. auto button = memnew(Button);
  3. // ...but what about this?
  4. auto result = EditorNode::get_singleton()->get_complex_result();

请记住,拉取请求的审核者一般是没有悬停文档的。大多数情况下,审核者是用 GitHub 的在线查看器审核拉取请求的。

为了避免需要在难以抉择的极端情况上下定论的情况发生,我们选择禁止 auto,不允许特事特办。感谢您的理解。

Lambda

应该保守地使用 lambda,需要在能让代码更快或者更简单的同时,不妨碍可读性。请在拉取请求中使用 lambda 前先询问。

#pragma once 指令

为了遵循现有风格,请在新文件中使用标准的基于 #ifdef 的包含保护,不要使用 #pragma once

参见

C++ 和 Objective-C 文件中 include 的排序规范请参阅 标头引入