Rust中的空指针优化是什么?

Jal*_*Jal 10 rust

学习Rust中,链接列表完全过多,作者提到:

但是,如果我们有一种特殊的枚举:

enum Foo {
    A,
    B(ContainsANonNullPtr),
}
Run Code Online (Sandbox Code Playgroud)

空指针优化启动,这消除了标签所需的空间.如果变体是A,整个枚举设置为全部0.否则,变体是B.这是有效的,因为它B永远不会全部0,因为它包含一个非零指针.

我想作者说的是(假设A是4位,B是4位)

let test = Foo::A
Run Code Online (Sandbox Code Playgroud)

内存布局是

0000 0000
Run Code Online (Sandbox Code Playgroud)

let test = Foo::B
Run Code Online (Sandbox Code Playgroud)

内存布局是

some 8 bit non 0 value
Run Code Online (Sandbox Code Playgroud)

究竟在这里优化了什么?两种表示都不总是8位当作者声称时它是什么意思

这意味着&,&mut,Box,Rc,Arc,Vec,并把在当鲁斯特其他几个重要的类型有没有开销Option

Lil*_*ard 20

空指针优化基本上意味着如果你有一个包含两个变量的枚举,其中一个变量没有关联数据,而另一个变量具有关联数据,其中所有零的位模式不是有效值,那么枚举本身将获取与相关值完全相同的空间量,使用全零位模式指示它是另一个变体.

换句话说,这意味着它Option<&T>的大小完全相同,&T而不需要额外的单词.

  • 编译器具有有关各种类型的内存布局的内置知识。例如,它知道“&amp;”引用永远不能为空。它还知道“String”和“Vec”永远不可能全为零;接下来的实现中,“String”由“Vec”支持,“Vec”由“RawVec”支持,“RawVec”由“Unique”支持,其中包含“*const T”,但有一个编译器属性声明它不能为空。类似地,有一个 stdlib `NonNull&lt;T&gt;` 类型,其作用就像一个永远不能为 null 的 `*mut T` 。 (6认同)
  • 详细来说,空字符串和向量并不指向 null,它们指向一个容量为零的固定非空地址。与可以廉价创建的其他容器(例如 HashMap)相同。Rust stdlib 非常努力地避免指针中出现空值,因此可以为诸如空指针优化之类的事情保留全零值。 (4认同)

red*_*ime 12

enum是一个标记的联盟.没有优化它看起来像

Foo::A;    // tag 0x00 data 0xXX
Foo::B(2); // tag 0x01 data 0x02
Run Code Online (Sandbox Code Playgroud)

空指针优化删除单独的标记字段.

Foo::A;    // tag+data 0x00
Foo::B(2); // tag+data 0x02
Run Code Online (Sandbox Code Playgroud)

  • 考虑到“0x00”是整数的有效位模式,第二个示例似乎有点不准确,因此“Foo::A”和“Foo::B(0)”的含义都不明确。 (11认同)

Ste*_*Lau 10

我也学习了太多的链表,也许这个代码片段可以加深你的理解

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
}
Run Code Online (Sandbox Code Playgroud)