Rust胖指针

4,571 阅读2分钟

我们已经知道编译器对类型是有严格要求:编译时已知使用内存大小

所以对于DST类型,编译器是不接受的,要让编译器接受DST类型,必须绕一个弯:借助胖指针(fat pointer)

胖指针是指针类型的一种特殊指针:

  1. 指向静态sized类型值的常规指针;对于数组[i32; 3]而言,& [i32; 3]就是常规指针;
  2. 指向动态sized类型值的胖指针:使用的内存空间是常规指针所使用的内存空间的两倍,切片(& [i32])这种指针是胖指针(fat pointer);trait对象和切片变量的类型其实是胖指针类型!

为什么Rust编译器会把 &[i32] 这种类型的指针当成胖指针处理呢?因为在Rust眼里,[i32]也是一个合理的类型。它代表由 i32 类型组成的数组,然而长度在编译阶段不确定。

Rust代码中不能直接声明一个变量的类型是 DST 类型,因为编译器没办法知道怎么为这种变量分配内存。

但是,指向DST类型的指针是可以存在的,因为指针的大小总是固定的。

Rust中有一个重要的 trait Sized,可以用于区分一个类型是不是 DST类型。

所有的 DST 类型都不受 Sized约束。

我们可以在泛型约束中使用 Sized、!Sized、?Sized 三种写法:

  1. T:Sized 代表类型必须是编译期确定大小的,

  2. T:!Sized 代表类型必须是编译期不确定大小的,

  3. T:?Sized 代表以上两种情况都可以。

在泛型代码中,泛型类型参数默认受 Sized 约束,因为这是最普遍最常见的情况。

如果我们希望一个泛型参数也可以支持 DST 类型,那么就应该为它专门加上 ?Sized 约束