当你有一个Option<&T>,编译器知道NULL永远不是&Tencodes the None variant as NULL instead的可能值.这样可以节省空间:

use std::mem;

fn main() {
    assert_eq!(mem::size_of::<&u8>(), mem::size_of::<Option<&u8>>());
}

但是,如果对非指针类型执行相同操作,则不需要额外的位来存储该值,并且需要额外的空间:

use std::mem;

fn main() {
    // fails because left is 1 and right is 2
    assert_eq!(mem::size_of::<u8>(), mem::size_of::<Option<u8>>()); 
}

总的来说,这是正确的.然而,我想 Select 优化,因为我知道我的类型有一些不可能的值.作为一个虚构的例子,我可能有一个有年龄的玩家角色.年龄可能未知,但永远不会高达255岁:

struct Age(u8);

struct Player {
    age: Option<Age>,
}

我希望能够告知优化器这个约束——Age永远不能是255,所以将该位模式用作None是安全的.这可能吗?

推荐答案

从Rust 1.28开始,您可以使用std::num::NonZeroU8(和朋友).这就像一个包装器,告诉编译器一个数字的内容将包含一个文本零.这也是Option<Box<T>>是指针大小的原因.

下面的示例展示了如何创建Age并读取其有效负载.

use std::num::NonZeroU8;

struct Age(NonZeroU8);

impl Age {
    pub fn new(age: u8) -> Age {
        let age = NonZeroU8::new(age).expect("Age cannot be zero!");
        Age(age)
    }

    pub fn age(&self) -> u8 {
        self.0.get()
    }
}

struct Player {
    age: Option<Age>,
}

fn main() {
    println!("size: {}", std::mem::size_of::<Player>());
    // Output: size: 1
}

Rust相关问答推荐

在rust中如何修改一个盒装函数并将其赋回?

两个相关特征的冲突实现错误

如果成员都实现特征,是否在多态集合上实现部分重叠的特征?

在Rust中宏的表达式中提取对象

如何将单个 struct 实例与插入器一起传递到Rust中的映射

在Rust中克隆源自INTO_ITER()的迭代器的成本?

在铁 rust 中,如何一次只引用几件事中的一件?

为什么 `Deref` 没有在 `Cell` 上实现?

为什么 Rust 创建的 f32 小于 f32::MIN_POSITIVE?

可选包装枚举的反序列化

为什么 Rust 字符串没有短字符串优化 (SSO)?

Rust 打包在 .deb 中

如何在 Rust 的 Hyper 异步闭包中从外部范围正确读取字符串值

错误:将自定义 proc_macro 与用Rust 的宝贝编写的属性一起使用时,无法在此范围内找到属性

返回引用字符串的future

仅当满足外部条件时如何添加到 actix web 的路由

使用泛型作为关联类型,没有幻像数据

如何用另一个变量向量置换 rust simd 向量?

在传输不可复制的值时实现就地枚举修改

在 Rust 中组合特征的不同方法是否等效?