为啥这个 Rust 枚举不小?
Posted
技术标签:
【中文标题】为啥这个 Rust 枚举不小?【英文标题】:Why is this Rust enum not smaller?为什么这个 Rust 枚举不小? 【发布时间】:2019-12-11 02:19:11 【问题描述】:考虑一下这个愚蠢的枚举:
enum Number
Rational
numerator: i32,
denominator: std::num::NonZeroU32,
,
FixedPoint
whole: i16,
fractional: u16,
,
Rational 变体中的数据占 8 个字节,FixedPoint 变体中的数据占 4 个字节。 Rational 变体有一个必须为非零的字段,所以我希望枚举布局规则将其用作鉴别器,零表示存在 FixedPoint 变体。
但是,这个:
fn main()
println!("Number = ", std::mem::size_of::<Number>(),);
打印:
Number = 12
因此,枚举为显式鉴别器获得空间,而不是利用非零字段的存在。
为什么编译器不能使这个枚举更小?
【问题讨论】:
这个之前已经讨论过了。我想答案是编译器还不够聪明(还) @DenysSéguret:布局是Rational::numerator
和FixedPoint
重叠,而Rational::denominator
不与任何东西重叠。如果Rational::denominator
占用的内存为0,则为FixedPoint
,否则为Rational
。
相关:***.com/questions/16504643/…
这是issue #46213。几年前,我尝试自己实施它,但没有成功。但是,与此同时,rustc 中的情况发生了变化,我认为现在可能更容易了。
【参考方案1】:
尽管像Option<&T>
can be handled without reserving space for the tag 这样的简单案例,rustc 中的布局计算器仍然不够聪明,无法优化具有多个非空变体的枚举的大小。
这是 GitHub 上的 issue #46213。
你问的情况很明确,但也有类似的情况,枚举看起来应该优化,但实际上不可能,因为优化会排除内部参考;例如,见Why does Rust use two bytes to represent this enum when only one is necessary?
【讨论】:
以上是关于为啥这个 Rust 枚举不小?的主要内容,如果未能解决你的问题,请参考以下文章