当你有一个Option<&T>
,编译器知道NULL
永远不是一个可能的值&T
, and 编码None变体为NULL instead https://stackoverflow.com/q/16504643/155423。这可以节省空间:
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>>());
}
一般来说,这是正确的。但是,我想选择进行优化,因为我知道我的类型具有某些不可能的值。作为一个虚构的例子,我可能有一个有年龄的玩家角色。年龄可能未知,但绝不会高到255
:
struct Age(u8);
struct Player {
age: Option<Age>,
}
我希望能够告知优化器这个约束 -Age
永远不可能255
,所以使用该位模式是安全的None
。这可能吗?
从 Rust 1.28 开始,您可以使用std::num::NonZeroU8 https://doc.rust-lang.org/std/num/struct.NonZeroU8.html(和朋友)。它充当一个包装器,告诉编译器数字的内容将never包含一个字面量零。这也是为什么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
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)