C++ 和 Rust 常常谈及零成本抽象。简而言之:

What you don’t use, you don’t pay for. What you do use, you couldn’t hand code any better.[1]

零成本抽象意味着两件事:[2]

  1. 零成本抽象意味着高级编程概念,如泛型、集合等不会带来运行时开销,只有编译期开销。对零成本抽象的任何操作都至少比手写一样好。

  2. 如果不使用某些功能,则不会承受这些功能带来的负面影响。比如 Rust 如果不使用 async,则不会承受 runtime 的开销。

C++ 中的零成本抽象

C++ 中的零成本抽象包含多种机制:

  • 编译期多态。C++ 模板提供了泛型编程,运行在编译期执行计算任务,从而避免运行时开销。

  • 函数内联。编译器可以将函数调用内联,从而避免函数调用的开销。

  • 静态分发。C++ 支持静态绑定,也就是说在编译期就确定对象调用的函数,无须动态分发。

Rust 中的零成本抽象

Rust 中的零成本抽象包括了:

  • 函数内联。

  • 静态分发。

  • 生命周期。Rust 在编译期确定对象的生命周期,而不是在运行时检测。

  • 所有权。Rust 在编译期确定对象的所有权,而不是在运行时检测。

  • async。不使用 async 函数就没有 async 运行时开销。

  • 动态分发。不使用动态分发就没有动态分发的开销。

  • ZST(Zero Size Type)。空类型不会占据任何空间(和 C++ 不同)。

    ZST 类型包括了:

    • 空元组:()

    • 空数组:[u8; 0]

    • 空结构体:struct A;

    ZST 的引用也是非空且对齐的,其大小为 usize。

  • 空类型。不可实例化的空类型可用在接口级别表示不可达的条件。Rust 编译器会考虑将 Result<T, Void> 优化为 T。[3]

  • repr(transparent) 允许将类型布局声明为内部类型相同。从而达到零成本抽象的目的。比如 UnsafelCell<T> 相比 <T> 不会有任何开销。

和 Java/Go 对比

  1. Go 带有运行时,无论你是否使用协程都需要为协程付费。

  2. Java 默认情况下所有的函数都是虚函数,都需要为动态分发付费。

  3. Go/Java 带有 Gc,无须管理内存。但是代价是 GC 导致的程序暂停。

Last moify: 2025-03-27 01:52:43
Build time:2025-07-18 09:41:42
Powered By asphinx