为什么Box在内存中需要16个字节,但是引用的片只需要8个? (在x64机器上)

问题描述 投票:14回答:2

考虑:

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个?

rust
2个回答
17
投票

Box<T>基本上是*const T(实际上它是围绕Unique<T>的新型,它本身是NonNull<T>PhantomData<T>(对于dropck),但为了简单起见,我们坚持使用*const T)。

Rust中的指针通常与size_of::<usize>()具有相同的大小,除非Tdynamically sized type(DST)。目前,Box<DST>的大小是2 * size_of::<usize>()(在撰写本文时,确切的表示形式并不稳定)。指向DST的指针称为FatPtr

目前,有两种DST:切片和特征。切片的FatPtr定义如下:

#[repr(C)]
struct FatPtr<T> {
    data: *const T,
    len: usize,
}

注意:对于特征指针,len被指向vtable的指针替换。

有了这些信息,您的问题就可以得到解答:

  • Box<i8>i8是一个大小类型=>基本上与*const i8相同=> 8字节大小(64位指针宽度)
  • Box<[i8]>[i8]是DST =>与FatPtr<i8>基本相同=> 16字节大小(64位指针宽度)
  • Box<&[i8]>&[i8]不是夏令时。它与*const FatPtr<i8> => 8字节大小基本相同(64位指针宽度)

3
投票

引用的大小取决于引用类型的“大小”:

  • 对大小类型的引用是指向内存地址的单个指针。
  • 对unsized类型的引用是指向内存和指向数据大小的指针。这就是所谓的fat pointer#[repr(C)] struct FatPtr<T> { data: *const T, len: usize, }

Box是一种指向堆的特殊指针,但它仍然是一个指针。

知道了,你理解:

  • Box<i8>是8个字节,因为i8的大小,
  • Box<&[i8]>是8个字节,因为参考大小,
  • Box<[i8]>是16个字节,因为切片是未分级的。
© www.soinside.com 2019 - 2024. All rights reserved.