【问题标题】: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
  • 这是issue #46213。几年前,我尝试自己实施它,但没有成功。但是,与此同时,rustc 中的情况发生了变化,我认为现在可能更容易了。

标签: enums rust memory-layout


【解决方案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?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-12
    • 2017-12-05
    • 2021-01-04
    • 1970-01-01
    相关资源
    最近更新 更多