Rust 我不知道';我不理解切片和引用之间的区别
我不明白切片和引用之间的区别。Rust 我不知道';我不理解切片和引用之间的区别,rust,reference,slice,terminology,Rust,Reference,Slice,Terminology,我不明白切片和引用之间的区别。&String和&str之间有什么区别?我在网上读到一些东西,说引用是一个瘦指针,而slice是一个胖指针,但我不知道,似乎也找不到这两个词的意思。我知道切片可以强制成为引用,但它是如何做到的?什么是Deref特征?在Rust中,切片是长度不同的同质类型数据的连续块 这是什么意思 [u8]是一个切片。在内存中,这是一个u8s块。切片本身就是数据。但是,很多时候,人们把和[u8]看作一个片段。和[u8]是指向该数据块的指针。该指针包含两个内容:指向数据本身的指针和数
&String
和&str
之间有什么区别?我在网上读到一些东西,说引用是一个瘦指针,而slice是一个胖指针,但我不知道,似乎也找不到这两个词的意思。我知道切片可以强制成为引用,但它是如何做到的?什么是Deref特征?在Rust中,切片是长度不同的同质类型数据的连续块
这是什么意思
是一个切片。在内存中,这是一个[u8]
s块。切片本身就是数据。但是,很多时候,人们把u8
看作一个片段。和[u8]
是指向该数据块的指针。该指针包含两个内容:指向数据本身的指针和数据的长度。由于它包含两个内容,因此称为胖指针。和[u8]
也是一个参考(在本例中也可以被视为一个指针,*),但我们已经知道,无论它指向什么,都将是一个&u8
。因此,它是一个细指针,因为它只有一个元素 我们保证u8
中的所有数据都属于[u8]
类型 由于您的u8
只是定义为[u8]
类型的连续内存块,因此没有编译时定义它的大小。因此,我们需要将其长度存储在指向它的指针中。我们也不能将其放在堆栈上(这意味着:我们不能有一个仅是u8
**的局部变量)[u8]
- A
是[T]
s的一部分。对于任何给定的T
,只要T
本身是一个大小合适的类型***,我们就可以想象一个类型T
李>[T]
是字符串的一部分。它保证是有效的UTF-8文本,这就是它与str
的区别所在。Rust可能已经放弃了有效的UTF-8担保,只是将[u8]
中的所有其他内容定义为str
的一部分李>[u8]
let my_array: [u32; 3] = [1, 2, 3];
我们可以将my_数组
切成[u32]
如下:
let my_slice: [u32] = my_array[..];
但由于我们不能拥有大小未知的局部变量,因此必须将其置于引用下:
let my_slice: &[u32] = &my_array[..];
切片的意义在于,无论数据来自何处,它都是处理连续数据块的一种非常灵活的方法(限制生命周期)。我可以很容易地制作我的_数组
一个Vec
,这是堆分配的,它仍然可以工作
&String和&str之间有什么区别
&String
是对整个字符串对象的引用。Rust中的字符串对象本质上是一个Vec
。Vec
包含指向它“包含”的数据的指针,因此您的&String
可以被认为是&str
。这就是为什么我们可以做以下任何一项:
let my_string: String = "Abc".to_string();
let my_str: &str = &my_string[..]; // As explained previously
// OR
let my_str: &str = &*my_string;
对这一点的解释让我想到你的最后一个问题:
德里夫的特点是什么
Deref
特征是一种描述解引用(*
)运算符的特征。正如您在上面所看到的,我能够执行*我的字符串
。这是因为String
实现了Deref
,它允许您取消对字符串的引用。类似地,我可以将Vec
解引用为[T]
但是,请注意,Deref
特征用于的地方比使用*
的地方多:
let my_string: String = "Abc".to_string();
let my_str: &str = &my_string;
如果我尝试将类型为&T
的值分配到类型为&U
的位置,则Rust将尝试取消对我的T
的引用,次数与获得U
所需次数相同,同时至少保留一个引用。类似地,如果我有一个&&&&&&&&&&&&T
,并且我尝试将它分配给&&&&&&&&&&U
,它仍然可以工作
这称为解除强制:自动将&T
转换为&U
,其中一定量的*T
将导致U
- *:原始指针
*const T
和*mut T T
与引用的大小相同,但被编译器视为不透明。编译器不能保证原始指针后面的内容,甚至不能保证它们正确对齐。因此,取消引用是不安全的。但是由于Deref
特性定义了一个安全的Deref
方法,因此取消对原始指针的引用是特殊的,也不会自动完成
- **:这也包括其他动态大小的类型,如trait对象和
extern type
s。这还包括struct
s,其中还包含一个动态大小的类型作为其最后一个成员,尽管这些类型很难正确构造,但将来使用强制化
特性将变得更容易。通过使用允许使用动态大小局部变量的unsized_locals
nightly功能,可以使所有这些(外部类型除外)无效
- ***:Sized类型是编译时已知大小的所有类型。你可以一般地识别它们;给定类型
T
,T
的大小在编译时已知,如果T:Sized
。如果T:?Sized
,则其大小可能在编译时未知(T:?Sized
是调用方最灵活的要求,因为它接受任何内容)。因为切片需要da