Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers “a”是什么;胖指针;?_Pointers_Rust - Fatal编程技术网

Pointers “a”是什么;胖指针;?

Pointers “a”是什么;胖指针;?,pointers,rust,Pointers,Rust,我已经在一些上下文中读过“胖指针”一词,但我不确定它的确切含义以及它在Rust中的使用时间。指针似乎是普通指针的两倍大,但我不明白为什么。它似乎也与特征对象有关。术语“胖指针”用于指对动态大小类型(DST)-切片或特征对象的引用和原始指针。胖指针包含一个指针加上一些使DST“完整”的信息(例如长度) Rust中最常用的类型不是DST,而是编译时已知的固定大小。这些类型实现。即使是管理动态大小的堆缓冲区的类型(如Vec)也是size,因为编译器知道Vec实例在堆栈上占用的确切字节数。目前锈菌中有四

我已经在一些上下文中读过“胖指针”一词,但我不确定它的确切含义以及它在Rust中的使用时间。指针似乎是普通指针的两倍大,但我不明白为什么。它似乎也与特征对象有关。

术语“胖指针”用于指对动态大小类型(DST)-切片或特征对象的引用和原始指针。胖指针包含一个指针加上一些使DST“完整”的信息(例如长度)

Rust中最常用的类型不是DST,而是编译时已知的固定大小。这些类型实现。即使是管理动态大小的堆缓冲区的类型(如
Vec
)也是
size
,因为编译器知道
Vec
实例在堆栈上占用的确切字节数。目前锈菌中有四种不同的DST


切片(
[T]
str
) 类型
[T]
(对于任何
T
)都是动态调整大小的(特殊的“字符串片段”类型
str
)。这就是为什么您通常只将其视为
&[T]
&mut[T]
,即在引用后面。此引用是所谓的“胖指针”。让我们检查一下:

dbg!(尺寸::());
dbg!(尺寸::());
dbg!(尺寸::());
这将打印(进行一些清理):

size_of::()=8
尺寸单位::()=8
尺寸单位::()=16
因此,我们看到对像
u32
这样的普通类型的引用有8个字节大,对数组
[u32;2]
的引用也有8个字节大。这两种类型不是DST。但由于
[u32]
是DST,对它的引用是DST的两倍大在切片的情况下,“完成”DST的附加数据只是长度。因此可以说
&[u32]
的表示形式如下:

struct SliceRef{
ptr:*常数u32,
len:使用,
}

特征对象(
dyn Trait
) 当使用trait作为trait对象(即类型擦除、动态调度)时,这些trait对象是dst。例如:

trait动物{
fn说话(和自我);
}
结构猫;
猫科动物{
fn讲话(自我){
println!(“喵”);
}
}
dbg!(尺寸::());
dbg!(尺寸::());
这将打印(进行一些清理):

size_of::()=8
尺寸单位::()=16
同样,
&Cat
仅为8字节,因为
Cat
是一种普通类型。但是
dyn Animal
是一个特征对象,因此具有动态大小。因此,
&dyn Animal
的大小为16字节

对于trait对象,完成DST的附加数据是指向vtable(vptr)的指针。这里我无法完全解释vtables和vptr的概念,但它们用于在此虚拟调度上下文中调用正确的方法实现。vtable是一段静态数据,基本上只包含每个方法的函数指针。因此,对特征对象的引用基本上表示为:

struct TraitObjectRef{
数据:*const(),
vptr:*常数(),
}

(这是不同于C++的,抽象类的VPTR存储在对象中,这两种方法都有优点和缺点)。
自定义DST 实际上,可以通过最后一个字段是DST的结构创建自己的DST。然而,这是相当罕见的。一个突出的例子是

std::path::path

指向自定义DST的引用或指针也是fat指针。附加数据取决于结构中DST的类型


例外:外部类型 在中,引入了
外部类型
功能。外部类型也是DST,但指向它们的指针不是fat指针。或者更确切地说,正如RFC所说:

在Rust中,指向DST的指针携带有关所指向对象的元数据。对于字符串和切片,这是缓冲区的长度;对于trait对象,这是对象的vtable。对于外部类型,元数据只是
()
。这意味着指向外部类型的指针与usize的大小相同(即,它不是“胖指针”)

但是,如果您没有与C接口交互,您可能永远不必处理这些外部类型




上面,我们已经看到了不可变引用的大小。Fat指针对可变引用、可变原始指针和可变原始指针的作用相同:

size_of::<&[u32]>()       = 16
size_of::<&mut [u32]>()   = 16
size_of::<*const [u32]>() = 16
size_of::<*mut [u32]>()   = 16
size_of::()=16
尺寸单位::()=16
尺寸单位::()=16
尺寸单位::()=16

顺便说一句,术语本身并不是特定于锈菌的。Fat指针通常是指除了所指向对象的地址之外,还存储一些额外数据的指针。如果指针包含一些标记位,并且取决于这些标记位,指针有时根本不是指针,则称为标记指针表示。(例如,在许多Smalltalks虚拟机上,以1位结尾的指针实际上是31/63位整数,因为指针是字对齐的,因此永远不会以1结尾。)HotSpot JVM将其胖指针称为OOPs(面向对象指针)。只是一个建议:当我发布一个问答对时,我通常会写一个小注释,解释这是一个自我回答的问题,以及为什么我决定发布它。看看问题中的脚注:@GerardoFurtado我最初在这里贴了一条评论,解释了这一点。但现在它被移除了(不是我)。但是,是的,我同意,这样的笔记通常是有用的@Jörg W Mittag