为啥这个 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::numeratorFixedPoint 重叠,而Rational::denominator 不与任何东西重叠。如果Rational::denominator占用的内存为0,则为FixedPoint,否则为Rational 相关:***.com/questions/16504643/… 这是issue #46213。几年前,我尝试自己实施它,但没有成功。但是,与此同时,rustc 中的情况发生了变化,我认为现在可能更容易了。 【参考方案1】:

尽管像Option&lt;&amp;T&gt;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 枚举不小?的主要内容,如果未能解决你的问题,请参考以下文章

rust option 枚举

Rust 枚举

Rust语言教程 - if let表达式与枚举进阶

Rust语言教程 - if let表达式与枚举进阶

Rust语言教程 - if let表达式与枚举进阶

Rust语言教程 - if let表达式与枚举进阶