rust重点

不是每个trait都可以作为tarit对象被使用,这和类型大小是否确认有关。每个trait都包含一个隐式的类型参数Self,代表实现该tarit的实际类型。Self默认有一个隐式的tarit限定?Sized,形如 Self:?Sized。?Sized trait包含了所有的动态大小类型金额所有的可确定大小的类型。Rust中大多数类型都是可确定的,就是

必须满足下面2条规则才可以当作trait对象使用:

  1. trait的Self不能被限定为Sized。
  2. trait中所有的方法都必须是对象安全的。

而对象安全的方法必须满足一下三点之一:

  1. 方法受Self:Sized约束
  2. 方法签名同时满足以下三点:
    (1)必须不包含任何泛型参数。
    (2)第一个参数必须为Self类型或可以解引用为Self的类型
    (3)Self不能出现在第一个参数以外的地方,包括返回值
  3. trait中不能包含关联常量。

在实践中,只涉及到两条规则。如果一个 trait 中所有的方法有如下属性时,则该 trait 是对象安全的:

  • 返回值类型不为 Self

  • 方法没有任何泛型类型参数

  • 每个文件定义一个模块。lib.rs定义了一个和自己crate同名的模块;一个mod.rs定义了一个它所在文件夹名字的模块;其他的每个文件定义了一个同文件名的模块。

  • 二进制crate的root必须是main.rs,库crate的root必须是lib.rs

  • 单元测试通常和所测试的代码在同一个文件

  • 集成测试,样例,benchmarks 都必须像其他用户一样导入crate,只能用公开的API。

闭包

  1. 如果闭包中没有捕获任何环境变量,则默认自动实现Fn
  2. 如果闭包中捕获了复制语义类型的环境变量,则
    • 如果不需要修改环境变量,无论是否使用了move,均会自动实现Fn
    • 如果需要修改环境变量,则自动实现FnMut
  3. 如果闭包中捕获了移动语义类型的环境变量,则
    • 如果不需要修改,且没有使用move,则自动实现FnOnce
    • 如果不需要修改,且使用了move,则自动实现Fn
    • 如果需要修改,则自动实现FnMut
  4. 使用move,如果捕获的变量是复制语义类型的,则闭包本身会自动实现Copy/Clone,否则不会。

每个闭包表达式都是一个独立的类型,这会有一些不便,如不能把不同的闭包保存到一个数组中,但这可以通过把闭包当做trait对象来解决。把闭包放到Box中就可以构建一个闭包的trait对象,然后就可以当做类型来使用,

三者关系:
FnOnce-> FnMut -> Fn,即要实现Fn,必须先实现前面2个。

rust类型分为复制语义和移动语义,复制语义是指分配在栈上,所以复制的时候很简单,直接按位复制,不会出现内存不安全的情况。移动语义指分配在堆上,为了保证内存安全,才有了所有权系统,即一块内存只有有一个变量指向它。

对于复合类型来说,是复制还是移动,取决于其成员的类型,分为2种:

  • 结构体,枚举体:
    当成员全都是复制语义的时候,复合类型不会自动实现Copy,要手动实现Derive(Copy,Clone),此时复合类型才是复制语义的。如果复合类型中的成员有移动语义的,则无法实现Copy。
  • 元组,数组,Option:类型会自动实现Copy,如果元素均为复制语义,则元组就是复制,不需要手动再Derive(Coyp,Clone),否则元组就是移动语义的。

共享可变状态是万恶之源

每个let都会创建一个默认的词法作用域,这个作用域就是它的生命周期(lifetime),就是在这个词法作用域中存活,出了就死亡。

解引用会获得所有权。

显式生命周期参数是为了解决跨函数借用,编译器无法检查的问题。它只用于编译器的借用检查,来防止垂悬指针。

'b: 'a的意思是b的存活时间长于a
结构体实例的生命周期应短于或等于任意一个成员的生命周期。

生命周期省略规则:
  • 每个输入上对应一个不同的生命周期参数
  • 如果只有一个输入,则输出生命周期等于这个输入的生命周期
  • 如果有self(&self,&mut self),则输出生命周期等于self 的生命周期
trait对象的生命周期默认以下规则:
  • trait对象的生命周期默认是'static
  • 如果实现trait的类型包括&'a x或&'a mut x,则默认生命周期就是'a
  • 如果实现trait的类型包含多个类似T:'a的从句,则生命周期需要明确指定
Cell和RefCell的区别:
  • Cell通过set/get来直接操作包裹的值,RefCell通过borrow/borrow_mut。
  • Cell一般适合复制语义类型,即实现了Copy,RefCell适合移动语义类型
  • Cell无运行时开销,不会再运行时panic,RefCell则有运行时开销,会panic

写时复制Cow

Cow是一个枚举体智能指针,包括2个可选项:

  • Borrowed:用于包裹引用
  • Woned:用于包裹所有者

cow提供的功能是:以不可变的方式访问内容,在需要可变借用或所有权的时候再克隆一份数据。cow要点:

  • Cow实现了Deref,所以可以直接调用T的不可变方法
  • 在需要修改T时,可以使用to_mut方法获取可变借用。该方法会克隆,且仅克隆一次。如果T本身有所有权,则调用to_mut不会发生克隆
  • 在需要修改T时,也可以用into_owned方法来获取一个拥有所有权的对象。如果T是借用类型,则会发生克隆,并创建新的有所有权的对象。如果T是所有权对象,则会将所有权转移到新的克隆对象。

你可能感兴趣的:(rust重点)