rust重点

2019-12-30  本文已影响0人  Jesse_996

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

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

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

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

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

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

闭包

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

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

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

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

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

共享可变状态是万恶之源

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

解引用会获得所有权。

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

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

生命周期省略规则:
trait对象的生命周期默认以下规则:
Cell和RefCell的区别:

写时复制Cow<T>

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

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

上一篇 下一篇

猜你喜欢

热点阅读