Memory management 为什么Nil会增加一个枚举大小,而不会增加另一个?如何为Rust枚举分配内存?

Memory management 为什么Nil会增加一个枚举大小,而不会增加另一个?如何为Rust枚举分配内存?,memory-management,data-structures,rust,Memory Management,Data Structures,Rust,如果我定义以下枚举,Nil不会增加枚举的大小: 使用std::mem::size\u of; enum Foo{ Cons(~char) } 枚举条{ 反对者(~char), 无 } 普林顿!(“{}”,大小为::()); 普林顿!(“{}”,大小为::()); // -> 4 // -> 4 另一方面: enum Foo{ Cons(字符) } enum Foo{ Cons(字符), 无 } 收益率: // -> 4 // -> 8 定义枚举时发生了什么?如何为这些结

如果我定义以下枚举,Nil不会增加枚举的大小:

使用std::mem::size\u of;
enum Foo{
Cons(~char)
}
枚举条{
反对者(~char),
无
}
普林顿!(“{}”,大小为::());
普林顿!(“{}”,大小为::());
// -> 4
// -> 4
另一方面:

enum Foo{
Cons(字符)
}
enum Foo{
Cons(字符),
无
}
收益率:

  // -> 4
  // -> 8

定义枚举时发生了什么?如何为这些结构分配内存?

枚举的一种简单方法是为其最大变量的内容分配足够的空间,再加上一个描述符。这是一个标准的标签工会

生锈比这个聪明一点。(这可能要聪明得多,但目前还不是。)它知道给定一个
~T
,至少有一个值该内存位置不能为零。因此,在像您的
enum{Cons(~T),Nil}
这样的情况下,它能够将其优化为一个单词,内存中的任何非零值表示
Cons(~T)
,内存中的零值表示
Nil


当您处理
char
时,无法进行优化:零是一个有效的码点。恰巧,
char
被定义为一个Unicode码点,因此实际上可以优化该空间中的变量,在该空间的末尾有大量的空闲位(Unicode字符只需要21位,因此在32位空间中我们有11个空闲位)。这证明了Rust的enum判别式优化目前并不特别聪明。

可能是因为第一个可以表示为指向值的指针和空指针(因此它的大小与指针的大小相同),猜猜您在github上检查过Rust源了吗?这将为您提供它们的具体实现。我不清楚,但那是我第一个要检查的地方。这是一个很好的答案。值得一提的是,2019年这个问题不再存在,只是为了好玩;我猜Rust的枚举判别式优化在几年内变得更好了美好的我不知道Rust现在可以使用无效的
char
值作为鉴别器!确认:
enum Bar2{Cons(char),Nil}println!(“{:x}”,不安全的{std::mem::transmute::(Bar2::Nil)})产量
110000
。理解这种方式:Unicode最多定义U+10FFFF,明确声明高于该值的值永远无效;所以Rust认为任何超过该点的东西都是一个判别值,并使用下一个值。