Rust的Option类型的开销是多少?

Thi*_*ilo 72 performance null-pointer rust

在Rust中,引用永远不能为null,因此如果您实际需要null,例如链接列表,则使用以下Option类型:

struct Element {
    value: i32,
    next: Option<Box<Element>>,
}
Run Code Online (Sandbox Code Playgroud)

与简单指针相比,在内存分配和解除引用步骤方面涉及多少开销?在编译器/运行时中是否存在一些"魔力",使得使用相同的构造或通过将指针包装在向量中,使用自己在非核心库中Option实现成本,或者成本更低?Optionenum

huo*_*uon 75

是的,有一些编译器魔法可以优化Option<ptr>为单个指针(大多数时候).

use std::mem::size_of;

macro_rules! show_size {
    (header) => (
        println!("{:<22} {:>4}    {}", "Type", "T", "Option<T>");
    );
    ($t:ty) => (
        println!("{:<22} {:4} {:4}", stringify!($t), size_of::<$t>(), size_of::<Option<$t>>())
    )
}

fn main() {
    show_size!(header);
    show_size!(i32);
    show_size!(&i32);
    show_size!(Box<i32>);
    show_size!(&[i32]);
    show_size!(Vec<i32>);
    show_size!(Result<(), Box<i32>>);
}
Run Code Online (Sandbox Code Playgroud)

打印以下尺寸(在64位机器上,因此指针为8个字节):

// As of Rust 1.22.1
Type                      T    Option<T>
i32                       4    8
&i32                      8    8
Box<i32>                  8    8
&[i32]                   16   16
Vec<i32>                 24   24
Result<(), Box<i32>>      8   16
Run Code Online (Sandbox Code Playgroud)

需要注意的是&i32,Box,&[i32],Vec<i32>全部使用非空的指针优化内部的Option!

  • 此外,这种优化发生在所有"类似选项"的枚举中,因此它也适用于用户定义的"选项". (28认同)
  • @Pajn 看起来,至少从 2020 年 3 月开始,[这种类型的优化*可以*堆叠](https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=0eef41a53fd8081b2f22eb7a54491004) 只要因为有足够多的否则无效的二进制表示。当然,不可空指针通常只有一种无效的二进制表示形式。 (8认同)
  • 另请注意,此优化不能叠加。这可以在示例的最后一行中看到。当您将 Ok 的类型指定为 () 时,该特定结果类型将成为“类似枚举的选项”,因此无法在选项级别进行优化。但如果您尝试使用“Result&lt;i32, i32&gt;”,您可以看到优化再次应用。 (5认同)