什么是Zero Cost Abstraction?Rust学习中相关概念疑问求解
零成本抽象的核心原则其实可以用两句话概括:
- 你没有用到的抽象特性,不会给你带来任何额外开销
- 你正在使用的抽象特性,运行时效率不会低于你手动写的底层实现
你理解的「消除运行时内存开销、提升运行速度」是它的典型表现之一,但不是全部的核心含义。
我们拿你提到的类型状态举个实际的例子就很容易懂:
假设你要实现一个串口驱动的库,要避免用户在串口还没初始化的时候就调用发送数据的方法。
如果不用类型状态的抽象,常规做法是给串口结构体加一个is_init的布尔标记位,每次调用发送方法的时候先判断这个标记位是否为真,不符合就返回错误。这种实现方式就带来了额外的运行时开销:多了一个布尔值的内存占用,每次发送数据都要多做一次条件判断。
而用类型状态的实现方式是定义两个没有任何数据的空标记类型:Uninitialized和Initialized,再把串口结构体定义为泛型结构体Serial<State>,只给Serial<Initialized>实现发送数据的方法。这个时候所有的合法性校验全部被转移到了编译期执行:如果用户拿未初始化的串口实例调用发送方法,编译阶段就会直接报错,根本不会留到运行时。而且因为这两个标记类型本身没有任何数据,编译完成后会被完全优化掉,运行时不会有任何额外的内存占用,也没有任何判断开销,最终的执行效率和你直接手写完全没有校验的底层串口发送代码完全一致。
再举个更常见的例子:Rust的迭代器。你用迭代器链式调用做过滤、映射、聚合操作,写出来的代码简洁易读,不需要自己处理循环边界,但是编译出来的汇编代码和你手写裸循环挨个处理元素的效率完全一样,甚至因为编译器可以基于迭代器做更多定向优化,效率还会更高。这就是零成本抽象的价值:你可以享受到高级抽象带来的代码可读性、安全性、可维护性提升,完全不需要为此牺牲运行时的性能。
内容的提问来源于stack exchange,提问作者KC S

