rust笔记
slice
String, Array和Vector都可以使用 &v[1..4]这样的语法获得slice,字符串的slice的类型是&str, 其它类型的slice是&[T], 只是名字不同,内部都是一个指针加上长度。
1 |
|
注意:&str不能使用for in 遍历,它没有实现Iterator。可以先调用as_bytes转换成&[u8]
dot operator
1 |
|
在进行方法调用时,不管是多少层都引用会被编译器还原成对应的值,然后根据参数定义(self, &self, &mut self)决定是传值还是传引用。
Deref
Deref主要是为了智能指针引入的trait,它的行为都是为了服务智能指针,如果不是智能指针不建议实现Deref,除了常见Box,Rc外,String,Vector等都是实现了Deref的。
1 |
|
If T
implements Deref<Target = U>
, and x is a value of type T
, then:
- In immutable contexts,
*x
(whereT
is neither a reference nor a raw pointer) is equivalent to*Deref::deref(&x)
. - Values of type
&T
are coerced to values of type&U
T
implicitly implements all the (immutable) methods of the typeU
.
在需要&str, &[T]的地方之所以能直接传String,Array,Vector的引用就是因为它们实现了Deref,所以根据规则2,它的类型会自动转换
AsRef
1 |
|
takes_user能接受User对象以及Moderator对象,因为它们都实现了AsRef,并且返回了&User, 而takes_user的参数类型是AsRef
impl Trait vs dyn Trait
https://www.ncameron.org/blog/dyn-trait-and-impl-trait-in-rust/
简单点说,impl Trait
在编译时就确定了具体类型, 它会像泛型参数一样展开生成具体类型的函数副本(单态化),所以基本没有多余开销(静态分发),但是dyn Trait
则不然, 内部实际上是用一个虚拟表来dispatch 函数调用(动态分发)。也就是说一个变量对应多种类型。
优缺点:
- impl Trait只能存在于函数的签名中,其它地方不能使用,比如你不能用这种语句定义变量:
let v: impl T;
- dyn Trait只能使用
&dyn trait
或者Box<dyn trait>
这种形式。 - impl Trait可以使用多个Trait,比如
impl T1+T2
但是dyn Trait不行 - dyn Trait 可以在一个变量中存储多个不同的具体类型,比如一个函数返回 dyn Trait, 那么函数体可以返回多个不同的具体类型,而impl Trait则只能返回相同的具体类型。这主要是因为impl Trait是要展开成具体类型的。
- 要使用 dyn Trait, 那对应的trait必须是对象安全的(object safe), object safe的条件如下
- trait的方法不能返回Self类型
- trait不能有泛型参数
1 |
|
智能指针
1 |
|
标准库中实现了智能指针的类型:
- Box
- Vec
, String - Rc
, Arc - Cell
, RefCell - RwLock, Mutex
RefCell, RwLock, Mutex都实现了内部可变性。
ref关键字
主要用于pattern match中,如果match后v的类型是T,那么用ref v去match,那么v的类型就是&T。
1 |
|
生命周期规则
第一条规则是每一个是引用的参数都有它自己的生命周期参数。换句话说就是,有一个引用参数的函数有一个生命周期参数:fn foo<’a>(x: &’a i32),有两个引用参数的函数有两个不同的生命周期参数,fn foo<’a, ‘b>(x: &’a i32, y: &’b i32),依此类推。
第二条规则是如果只有一个输入生命周期参数,那么它被赋予所有输出生命周期参数:fn foo<’a>(x: &’a i32) -> &’a i32。
第三条规则是如果方法有多个输入生命周期参数并且其中一个参数是 &self 或 &mut self,说明是个对象的方法(method)(译者注: 这里涉及rust的面向对象参见17章), 那么所有输出生命周期参数被赋予 self 的生命周期。第三条规则使得方法更容易读写,因为只需更少的符号。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!