目录
Rust 枚举型的空指针优化
2019-05-12
在很多编程语言中, 枚举型主要是为了限制值域. 一个函数的参数类型如果设置成枚举型, 就能通过类型的限制, 让开发者更不容易误用. 除此之外, 枚举型实际上也是类型理论中的 Sum 类型, 即它表示了多个 (子) 类型的集合. 这一点在 C++ 这种枚举型原生不关联其他数据的语言中可能感受不强, 但是在 Rust, Haskell 等语言中, 尤其是在还支持模式匹配的情况下, 可能感受就比较强. 比如以下代码:
1 | enum Result<T, E> { |
上面的代码中, some_result
这个变量的类型, 可以理解成要么是 Ok
, 要么是 Err
.
数据存储
由于一个枚举型变量的具体’子类型’无法完全在编译时判断, 所以在存储上处理 ‘payload’ 之外还需要一些信息来帮助判断到底是什么子类型. 比如在 C++ 中, 一个 union 的结构体一般都会在配上一个 enum 来表示 union 结构体中到底包含了什么数据. 在 Rust 中也是如此, 同时, 就像 union 一样, 一个 enum 值, 不管是什么子类型, 都需要分配最大可能子类型所需要的空间.
空指针优化
所谓空指针优化实际上可以理解为是某种优化的特殊形式. 如果子类型之间可以通过数据本身的特征区分, 那就不需要在存储多余的信息来区分了. 对于空指针优化这种具体情况, 我们用一个例子来说明:
1 | enum Foo { |
对于 Foo 的 B 子类型, 因为我们知道包含的指针一定不是 null, 所以如果我们发现内存中全是 0, 我们就知道是 A. 这个看上去好像不是一个很有用的场景, 但是在 Rust 中, 对于 &
, &mut
, Box
, Rc
, Arc
, Vec
和其他很多重要的类型, 如果把他们放在 Option
中, 就不需要额外的存储消耗.