In Learning Rust With Entirely Too Many Linked Lists,作者提到:
但是,如果我们有一种特殊的枚举:
enum Foo { A, B(ContainsANonNullPtr), }
空指针优化启动,消除了标记所需的空间。如果变体为
A
,则整个枚举设置为全部0
。否则,变体为B
。这是有效的,因为B
永远不可能都是0
,因为它包含一个非零指针。
我想作者说的是(假设A
是4位,而B
是4位)
let test = Foo::A
内存布局
0000 0000
但
let test = Foo::B
内存布局
some 8 bit non 0 value
这里有什么优化?并不是两个表示总是8位当作者声称
时它是什么意思这意味着
时的开销&
,&mut
,Box
,Rc
,Arc
,Vec
以及Rust中的其他几个重要类型都没有放入Option
答案 0 :(得分:15)
空指针优化基本上意味着如果你有一个包含两个变量的枚举,其中一个变量没有关联数据,而另一个变量具有关联数据,其中所有零的位模式不是有效值,那么枚举本身将占用与相关值完全相同的空间量,使用全零位模式来指示它是另一个变体。
换句话说,这意味着Option<&T>
与&T
的大小完全相同,而不需要额外的单词。
答案 1 :(得分:8)
enum
是标记的联合。没有优化,它看起来像
Foo::A; // tag 0x00 data 0xXX
Foo::B(2); // tag 0x01 data 0x02
空指针优化会删除单独的标记字段。
Foo::A; // tag+data 0x00
Foo::B(2); // tag+data 0x02
答案 2 :(得分:1)
我也学习了太多链表,也许这段代码可以加深你的理解
pub enum WithNullPtrOptimization{
A,
B(String),
}
pub enum WithoutNullPtrOptimization{
A,
B(u32),
}
fn main() {
println!("{} {}", std::mem::size_of::<WithNullPtrOptimization>(), std::mem::size_of::<String>()); // 24 24
println!("{} {}", std::mem::size_of::<WithoutNullPtrOptimization>(), std::mem::size_of::<u32>()); // 8 4
}