考虑:
fn main() {
// Prints 8, 8, 16
println!(
"{}, {}, {}",
std::mem::size_of::<Box<i8>>(),
std::mem::size_of::<Box<&[i8]>>(),
std::mem::size_of::<Box<[i8]>>(),
);
}
为什么拥有的切片占用16个字节,而引用的切片仅占用8个字节?
答案 0 :(得分:17)
Box<T>
基本上是*const T
(实际上是围绕Unique<T>
的新类型,它本身就是带有NonNull<T>
的{{1}}(对于dropck) ,但为简单起见,请坚持使用PhantomData<T>
。
Rust中的指针通常具有与*const T
相同的大小,除非size_of::<usize>()
是dynamically sized type(DST)。当前,T
的大小为Box<DST>
(在撰写本文时,确切的表示形式并不稳定)。指向DST的指针称为2 * size_of::<usize>()
。
当前,DST有两种:切片和特征。切片的FatPtr
定义如下:
FatPtr
注意:对于特征指针,#[repr(C)]
struct FatPtr<T> {
data: *const T,
len: usize,
}
被指向len
的指针代替。
有了这些信息,您的问题就可以得到答案:
vtable
:Box<i8>
是一种大小类型=>与i8
=>基本上相同,大小为8个字节(指针宽度为64位)*const i8
:Box<[i8]>
是DST =>与[i8]
=>基本上相同,大小为16个字节(指针宽度为64位)FatPtr<i8>
:Box<&[i8]>
不是 DST。它基本上与&[i8]
=> 8字节大小(指针宽度为64位)相同答案 1 :(得分:3)
引用的大小取决于引用类型的“大小”:
对未定义大小类型的引用是指向存储器和指向数据的大小的指针。这就是所谓的fat pointer:
#[repr(C)]
struct FatPtr<T> {
data: *const T,
len: usize,
}
Box
是一种特殊的指向堆的指针,但它仍然是一个指针。
知道这一点,您就会了解:
Box<i8>
是8个字节,因为i8
的大小,Box<&[i8]>
为8个字节,因为引用的大小已确定,Box<[i8]>
为16字节,因为切片未调整大小。