我对 Rust 中数据布局的心理模型是,所有结构体的大小都必须在编译时已知,这意味着它们的所有属性都必须在编译时递归地知道。这就是为什么你不能拥有一个只是一个特征的结构成员(以及为什么必须使用枚举来代替联合类型):大小无法知道,所以你必须使用其中之一
- 泛型,因此该特征在使用时会“具体化”为大小已知的结构
- 一个枚举,具有一组有限的可能大小已知的布局
- 一个
Box
,其大小已知,因为它只是一个指针
但是在 Path
的文档中,它说:
This is an unsized type, meaning that it must always be used behind a pointer like
&
orBox
. For an owned version of this type, seePathBuf
.
然而Path
既不是特征也不是通用结构,它只是一个普通的结构。
我认为这可能的思维模式出了什么问题?
我找到了this explanation of what dynamically-sized types are ,但我仍然不明白,我将如何制作自己的一个。这样做是为语言本身保留的特殊特权吗?
最佳答案
结构体可以包含单个未调整大小的字段,这使得结构体本身未调整大小。构造未调整大小的类型的值可能非常困难,通常只能通过使用 unsafe 将对已调整大小的变体的引用转换为未调整大小的变体来完成。
例如,可以使用 #[repr(transparent)]
使得可以像这样将 &[u8]
转换为 &MySlice
。此属性使类型保证以与其单个字段相同的方式表示。
#[repr(transparent)]
struct MySlice {
inner: [u8],
}
像这样转换切片是合理的:
impl MySlice {
pub fn new(slice: &[u8]) -> &MySlice {
// SAFETY: This is ok because MySlice is #[repr(transparent)]
unsafe {
&*(slice as *const [u8] as *const MySlice)
}
}
}
你可以例如如果切片不是有效的 ascii,则拒绝执行转换,现在您将拥有一个保证指向有效 ascii 的字节数组,就像 &str
是 &[u8]
保证是有效的 utf-8。
关于memory - 如何调整结构体的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61293115/