1 Star 0 Fork 11

coder_lw / wiki

forked from deepinwiki / wiki 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
rust.md 8.88 KB
一键复制 编辑 原始数据 按行查看 历史
htqx 提交于 2021-12-29 14:42 . rust 更新一些内容

rust 编程语言

前言

rust是最新的一个比较流行的系统开发语言,和c/c++一样是一个比较底层的编程语言。但是rust 的优势在于它有现代语言具备的高级抽象表达能力。

从技术讲, rust 比 c 带来了一个更多的抽象,相对 c++ 引入了零成本抽象的改进,从语言层面添加了一个新的概念,那就是所谓的“所有权和借用”。这导致了 rust 具备更陡峭的学习成本。

总的而言, rust 更加安全,能帮助程序员养成编写安全可靠代码的习惯,同时保持底层语言需要的高性能。

rust的核心概念

  1. 所有权(ownership):一个对象只有一个变量持有,又持有的变量的上下文负责释放内存。
    1. 移动语义(move):转移对象到另一个变量上,旧对象将失效。注意对象并不会发生实质的移动,这是语义上的。不要和内存上的移动混淆。
      1. 交换(swap):这里指内存上的移动。
    2. 复制语义(copy):由编译器实现的对旧对象的复制,产生一模一样的备份。
      1. 克隆(clone):用户自行实现的克隆代码。
  2. 借用(borrow):临时访问对象(不转移所有权)
    1. 统一时刻,只允许一个可写借用。
    2. 或允许多个只读借用。
    3. 传递(send):T:Send ,如果 T 没有被标记是 !Send 时。跨线程传递。
    4. 同步(sync): &T:Send。跨线程共享。
  3. 智能指针(smart point):持有包装对象的所有权,并向外部提供对内部对象的指针操作
    1. 装箱到堆内存:Box<T>
    2. 共享对象: Rc<T>
    3. 内部可写:RefCell<T>
      1. 支持同步: Mutex<T>
  4. 生命周期(lifetime):指针指向对象的有效范围的声明
    1. 函数返回:返回值的生命周期和参数存在某种映射关系(副本),返回值的有效范围从而得到提示,编译器可以以此作为审查的标准。
    2. 对象成员:成员指针指向的对象的生命周期必须大于主体(因为主体不能持有无效指针)
    3. 函数指针: fn / Fn
    4. 子类型: 'a:'b , ‘a 的作用范围大于 'b ,所以可以用 'a 的实参取代 'b。
      1. 协变:‘a->’b, 例:&'a 等大部分
      2. 逆变:'b->'a, 例:fn('b)
      3. 不变:无关。例: & mut &'a,内部可变类型的参数,协变逆变冲突的参数
    5. 高阶特征边界: for<'a> F:Fn(&'a a)->&'a b 和包含它的主体的生命周期无关,而是和自身参数 a 有关。
    6. 无界:没有关联生命周期,如没有对应输入的返回类型的生命周期,没有使用的结构生命周期。这类生命周期理论上无限长(比'static更长)。
    7. PhantomData: 幽灵数据,帮助类型给出形式化的定义
  5. 多态:一套接口多种实现,提高代码复用
    1. 特征:提供一组公共 api
      1. 函数:提供参数到返回值的映射,和内部执行产生的副作用,如打开数据库(有一些观点认为副作用是不好的)。函数是一段公共的代码块,是提供代码复用的基本单元。
      2. 方法:没有返回值的函数。
      3. 闭包:会捕获上下文相关变量的函数块。
      4. 函数签名:特征可以不提供具体的函数体,而只提供函数名,参数,和返回类型构成的函数签名。而具体的实现,由实现该特征的类型来实现。
    2. 泛型(特征约束):静态分发
      1. T : 任意类型,但没有可用 api
      2. T:S : 特征约束,可以使用特征 S 的 api
      3. 针对函数参数和返回值类型
      4. 针对结构成员
      5. 针对特征成员或自身
      6. 单态化:泛型将编译成具体类型(单独的),代价是代码膨胀,优势是没有运行时开销
    3. 特征对象:动态分发
      1. &dyn S: 该指针可以使用特征 S 的 api
      2. 限制:rust 使用胖指针来实现特征对象,即 (&data,&vtable),这个结构说明了,类型信息是静态编译的,和具体类型 T:S 有关。所以,即便 S:Y, &dyn S 也无法转换成 &dyn Y(但你仍然能主动提供信息,如 T:S,你得提供具体类型 T,从而得到 T-->Y,特征 S 自身信息是不足以完成这种转换的)。也就是无法实现其他类型中的子类型转换成基类。

所有权(ownership): 一个对象严格对应一个变量,赋值会移动所有权,即新变量取得该对象,而旧变量失去所有权,变为不可用状态。

生命周期:生命周期在很多语言中都有涉及。也就是一个对象从创建到死亡的过程。当拥有对象的变量离开上下文范围,对象可以自动的释放对象。这类似c++的析构机制。不过rust比c++有更加精细的定义的操控,这个也是rust的一个难点。

共享对象:所有权的副作用导致对象共享变得不可能,但是我们现实编程中又经常需要共享对象,怎么办?rust 在这个层面引入很多概念来解决这个问题,但是也带来非常多的复杂性。因此,这也是rust的一个难点。

只读共享对象: 如果一个对象是只读的,那么共享它实际上非常安全。rust 引入了“借用”这个概念,类似很多其他语言中的“引用”。使用借用()这个词,更能明确“所有权”和“借用”的区别。

可写共享对象: 如果一个对象可写,这会很麻烦。状态不一致导致很多程序bug,这也是c/c++这类语言不安全的重要原因,如何保证可靠的可写共享,这就要严格的控制相关的程序逻辑(即语义),而程序逻辑有各种可能性。有几种策略:1. 克隆,产生一份镜像,回到简单的所有权概念(非共享),之后再想办法回写。2.可写借用。同样是借用,但是可写,不过这个可写借用本质也是非共享的,因为只能存在一份唯一的可写借用,某种层度上也是类似普通的所有权,差别是所有权转移会导致生命周期中的范围发生改变,而可写借用不会。3. 内部可写。rust支持不安全上下文,通过内部的不安全上下文对对象状态进行修改,这中技术叫内部可写。以上可见,可写共享对象的安全性是严格和程序逻辑相关的,rust并不支持自动的安全的可写共享对象,但是有相关的技术让其变得易于编写(也许)。

跨线程共享对象:这个问题在多线程下表现得更加明显。和其他语言类似,rust 也支持async和await的组合。在 rust 中,它的实现方法是通过一个Future“特征”(类似其他语言中的接口),包含一个函数 poll(self:Pin<&mut Self>, cx:&mut Context<'_>)->Poll<Self::Output> 。其中self参数标识调用者的类型,即Pin<&mut Self>。这个泛型类型包含一个&mut Self的参数,意思是自身类型的可写借用。cx 参数实际功能是包含数据的回调函数。返回值是Poll枚举(类似c++加强版的联合),包含两种状态,一种是有Self::Output类型的返回值,一种是等待。从这个原型可以看出跨线程的共享对象,使用的是精心设计的数据结构,其核心就是可写借用。

跨线程的数据安全:首先,基于所有权的对象传递(send)是安全的。因为它同时将所有权和生命周期范围跨线程了。而,借用就没那么幸运,因为不同的线程结束的次序是不确定的,如果被借用的对象先消亡,那么就违反了语义,存在bug。通过托管给智能指针的方式,让对象从一个线程中转移到智能指针中,由其负责管理,实现了借用语义。而这种智能指针就称之支持同步(sync)的。进而,支持可变借用的智能指针还包括了内部可写的特性,支持加锁和解锁,然而这种方式在其他语言中也有,且并不高明,容易出错,需要程序员精心设计。

内部可写和智能指针:所谓智能指针,就是模拟借用功能,但具备封闭api管理的对象。语言层面的借用功能是有限的,它是和特定程序逻辑无关的,而智能指针就弥补了这个缺点。库开发人员通过开发不同功能的智能指针,让借用功能得到扩展。内部可写通过利用不安全上下文,对rust语言限制的只读共享作出修改,让写入共享对象变得可能(但同时也失去了编译器安全分析的保护)。从技术上来说,他们是以智能指针的方式来实现。

总结rust核心概念涉及的具体对象:

  1. let a : i32 = 5; : i32类型的变量a,关联对象(值5),所有权转移语义。即 let b = a; b 获得对象(值5),a失去对象,且无效不可用。

参考

  1. Rust编程语言入门教程(Rust语言/Rustlang)(视频): https://www.bilibili.com/video/BV1hp4y1k7SV?p=1
  2. 【译】探讨Rust中的动态分发(dynamic dispatch): https://zhuanlan.zhihu.com/p/248002546
1
https://gitee.com/coder_lw/wiki.git
git@gitee.com:coder_lw/wiki.git
coder_lw
wiki
wiki
master

搜索帮助