← 返回信息流
AI 资讯Hacker News·4 小时前

Orthodox C++:一种旨在提升代码质量与可维护性的C++编程规范

原标题:Orthodox C++

速览

Orthodox C++是由C++专家社区提出的一套编程规范,旨在解决C++代码风格混乱的问题。该规范强调代码的可读性、一致性和可维护性,为开发者提供了明确的编码指导。遵循Orthodox C++有助于提升团队协作效率,减少潜在的软件缺陷。

AI 深度解读

Orthodox C++:回归极简的 C++ 编程哲学

背景

C++ 语言自诞生以来,其复杂性一直备受争议。随着 C++11、C++14、C++17 乃至 C++20 等现代标准的推出,语言特性日益丰富,但也带来了学习曲线陡峭、编译时间增加以及代码维护难度加大等问题。

在 20 世纪 90 年代末,许多开发者曾热衷于使用当时最新的 C++ 特性,视其为“现代”编程的标志。然而,随着时间的推移,许多资深开发者发现,盲目追求新特性往往导致代码复杂度不必要的增加,甚至引入难以调试的问题(如 RTTI、异常处理和流式输入输出)。

“Orthodox C++”(正统 C++,有时也被称为 C+)正是在这种反思中诞生的一种编程风格或子集。它主张在 C++ 中剥离所有“不必要”的现代特性,回归到一种更简单、更易于理解、且能与旧编译器兼容的编程模式。其核心理念是:“在 C++ 内部,有一个更小、更干净的语言正在挣扎着想要出来。”——Bjarne Stroustrup。

核心内容

Orthodox C++ 并非一种新的编程语言,而是对 C++ 标准库和语言特性的一种严格限制和选择。它旨在通过限制语言功能的使用,来提高代码的可读性、可维护性以及跨平台兼容性。

1. 基本定义与示例

Orthodox C++ 是 C++ 的一个最小子集,它改进了 C 语言,但避免了所谓“现代 C++”中的所有非必要特性。其代码风格应尽可能接近 C 语言,使得任何熟悉 C 语言的开发者都能轻松阅读。

Hello World 示例:

#include <stdio.h>
int main()
{
    printf("hello, world\n");
    return 0;
}

2. 核心原则:做什么与不做什么

✅ 推荐做法

  • 使用类 C 的 C++:如果代码不需要更复杂的特性,就不要引入不必要的 C++ 复杂性。代码应尽可能让熟悉 C 语言的人也能读懂。
  • 适度使用元编程:仅在必要时使用,且必须能降低代码复杂度。避免为了炫技而过度使用元编程。
  • 谨慎对待新标准特性:对于当前标准引入的特性,建议等待下一个标准迭代使其更加成熟。例如,constexpr 在 C++11 中引入,但在 C++14 中才变得真正实用。

❌ 禁止或避免的做法

  • 不使用异常处理 (Exceptions)

    • 理由:异常处理是 C++ 中唯一需要复杂运行时系统支持的特性。即使不使用异常,它也会带来运行时开销(如对象构造/析构时的隐藏代码、try 块入口/出口的额外代码),并严重限制编译器的优化能力。此外,C++ 的异常规范在编译时并不强制检查,容易导致错误处理遗漏。更重要的是,异常风格与 C 语言常见的错误返回码风格不兼容,导致代码风格分裂。
  • 不使用 RTTI (运行时类型识别)

    • 理由:RTTI 增加了运行时开销和二进制大小,且在大多数情况下并非必需。
  • 不使用 C++ 运行时包装器

    • 做法:直接使用 C 运行时头文件,如 <stdio.h><math.h>,而不是 <cstdio><cmath> 等 C++ 包装头文件。
  • 不使用流 (Streams)

    • 做法:使用 printf 系列函数代替 <iostream><stringstream> 等流式输入输出。
  • 不使用 STL 中分配内存的组件

    • 理由:除非你不关心内存管理,否则应避免使用 std::vectorstd::string 等动态分配内存的 STL 容器。这主要出于对内存分配性能和控制力的考量,特别是在游戏开发等高性能领域(参考 Andrei Alexandrescu 的演讲及 AAA 游戏工作室的选择)。
  • 不使用 Modules (模块)

    • 理由
      1. 需要重写或重构代码。
      2. 丧失可移植性(模块二进制文件通常不可移植,仍需提供头文件)。
      3. 项目构建设置变得更加复杂。
      4. 依赖最新的工具链,旧版本编译器(如 Apple 的 Clang 早期版本)支持不完整。
      5. 结论:开发者除了获得“Nothing”(无优势)外,没有任何好处。

3. 何时可以使用现代 C++ 特性?

由于编译器、操作系统发行版等对 C++ 标准的采纳存在滞后,通常不建议立即使用新的语言特性。

  • 通用准则:如果当前年份 >= C++ 标准年份 + 5,则可以安全地选择性使用。

    • 例如:C++11 标准于 2011 年发布,那么在 2016 年及之后使用其特性通常是安全的。
    • 反例:如果代码需要 C++17 标准,而当前年份是 2016 年,这属于“简历驱动开发”(Resume Driven Development),对于开源项目而言,这会让其他开发者难以使用你的代码。
  • 最新更新 (2025年1月14日):Orthodox C++ 委员会批准选择性使用 C++20 特性。

关键要点

  • 极简主义:Orthodox C++ 是 C++ 的一个最小子集,旨在剥离复杂性,回归 C 风格的简洁性。
  • 性能与控制:通过避免异常、RTTI 和动态内存分配(STL 容器),减少运行时开销,提高性能可控性。
  • 可移植性与兼容性:代码可在旧编译器上构建,不依赖特定的模块系统,提高了跨平台和跨项目的兼容性。
  • 错误处理:摒弃异常,回归 C 风格的错误返回码,保持代码风格的一致性。
  • 输入输出:摒弃 iostream 流,使用 printf 系列函数。
  • 标准采纳滞后:新特性需等待至少 5 年才被广泛支持后才建议使用,避免“简历驱动开发”。
  • 元编程克制:仅在能降低复杂度时使用元编程,反对学术化的炫技。
  • 模块反对:认为 C++ Modules 带来复杂性而无实质收益,主张继续使用头文件。

意义与影响

Orthodox C++ 并非要取代现代 C++,而是为那些追求极致性能、简单性和可维护性的项目提供了一种替代方案。它在以下领域具有显著影响:

  1. 游戏开发:许多 AAA 游戏工作室(如 id Software 的 DOOM 3 BFG、Network Next SDK)采用类似 Orthodox C++ 的风格,以避免内存分配开销和确保对底层硬件的精细控制。
  2. 嵌入式系统:与 Embedded C++ 理念相似,Orthodox C++ 适用于资源受限的环境。
  3. 跨平台库开发:如 Qt(在禁用 RTTI 和异常时)、dear imgui 等项目,通过限制 C++ 特性使用,提高了代码的通用性和可集成性。
  4. 代码审查与维护:对于大型代码库,Orthodox C++ 的严格限制有助于降低新成员的学习门槛,减少因语言特性滥用导致的维护债务。

此外,存在如 Orthodoxy 这样的 Clang 编译器插件,可以自动禁用特定的 C++ 特性,帮助开发者强制执行 Orthodox C++ 规范。

总之,Orthodox C++ 是对 C++ 复杂性的一种反思和平衡,它提醒开发者:并非所有语言特性都是必需的,简单往往意味着更可靠、更高效和更易维护的代码。

查看原文 →bkaradzic.github.io