【Rust】20. Rust 的高级特征

在这里插入图片描述

20.1 不安全 Rust

在这里插入图片描述

20.1.1 不安全的超能力

在这里插入图片描述

20.1.2 解引用裸指针

  • 裸指针(raw pointers):类似于引用类型;和引用一样,裸指针是不可变或可变的,分别写作 *const T*mut T,这里的星号不是解引用运算符,它是类型名称的一部分
  • 在裸指针的上下文中,不可变意味着指针解引用之后不能直接赋值
  • 直接从保证安全的引用来创建他们(比如使用 as 来强转为某类型),可以知道这些特定的裸指针是有效,但是不能对任何裸指针做出如此假设
  • 裸指针与引用和智能指针的区别,如下 4 点
  • 允许忽略借用规则:可以同时拥有不可变和可变的指针(若通过可变指针修改数据,则可能潜在造成数据竞争!),或多个指向相同位置的可变指针
  • 不保证指向有效的内存
  • 允许为空
  • 不能实现任何自动清理功能

在这里插入图片描述
在这里插入图片描述

20.1.3 调用不安全函数或方法(一):基本概念

在这里插入图片描述

20.1.4 调用不安全函数或方法(二):创建不安全代码的安全抽象

  • slice::from_raw_parts_mut 函数是不安全的因为它获取一个裸指针,并必须确信这个指针是有效的
  • 裸指针上的 add 方法也是不安全的,因为其必须确信此地址偏移量也是有效的指针
  • 注意无需将 split_at_mut 函数的结果标记为 unsafe,并可以在安全 Rust 中调用此函数。我们创建了一个不安全代码的安全抽象,其代码以一种安全的方式使用了 unsafe 代码

在这里插入图片描述
在这里插入图片描述

20.1.5 调用不安全函数或方法(三):使用 extern 函数调用外部代码

在这里插入图片描述

20.1.6 访问或修改可变静态变量

  • 常量:
  • 可变静态变量:静态变量中的值有一个固定的内存地址(使用这个值总是会访问相同的地址);访问不可变静态变量是安全的
  • 可变静态变量:使用 mut 关键字来指定可变性;访问和修改可变静态变量都是 不安全 的,必须位于 unsafe 模块内

在这里插入图片描述

20.1.7 实现不安全 trait

在这里插入图片描述

20.1.8 访问联合体中的字段

在这里插入图片描述

20.1.9 何时使用不安全代码

在这里插入图片描述

20.2 高级 trait

20.2.1 关联类型:在 trait 定义中指定占位符类型

  • **关联类型(associated types)**是一个将类型占位符与 trait 相关联的方式,这样 trait 的方法签名中就可以使用这些占位符类型
  • 关联类型也会成为 trait 契约的一部分:trait 的实现必须提供一个类型来替代关联类型占位符
  • 作用:用于类型占位,不用重复多次仅修改类型来实现同一个功能

在这里插入图片描述

20.2.2 默认泛型类型参数和运算符重载

  • 默认参数类型主要应用:1、扩展类型而不破坏现有代码;2、在大部分用户都不需要的特定情况进行自定义

在这里插入图片描述
在这里插入图片描述

20.2.3 完全限定语法与消歧义:调用相同名称的方法

  • 同名问题:Rust 既不能避免一个 trait 与另一个 trait 拥有相同名称的方法,也不能阻止为同一类型同时实现这两个 trait,甚至直接在类型上实现开始已经有的同名方法也是可能的
  • 对于方法(有 self 参数):编译器默认调用直接实现在类型上的方法
  • 对于关联函数(没有 self 参数):直接调用定义于实现在类型中的关联函数
  • 完全限定语法:<Type as Trait>::function(receiver_if_method, next_arg, ...);,唯一地指定出哪个对象类型(type)所实现的哪个 trait 方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

20.2.4 父 trait 用于在另一个 trait 中使用某 trait 的功能

  • 父(超)trait(supertrait):在实现 trait 时通过 子模块: 父模块 指定其依赖的上一级父 trait,即可获得父 trait 的方法。比如:OutlinePrint: fmt::Display
  • 注意:需要同时满足子、父 trait 的实现要求!

在这里插入图片描述

20.2.5 newtype 模式用以在外部类型上实现外部 trait

在这里插入图片描述

20.3 高级类型

20.3.1 为了类型安全和抽象而使用 newtype 模式

在这里插入图片描述

20.3.2 类型别名用来创建类型同义词

  • 类型别名(type alias):使用 type 关键字来给予现有类型另一个名字,主要用途是减少重复

在这里插入图片描述
在这里插入图片描述

20.3.3 从不返回的 never type

  • ! 空类型 / 不返回类型:在函数从不返回的时候充当返回值,可以强转为任何其他类型

在这里插入图片描述
在这里插入图片描述

20.3.4 动态大小类型和 Sized trait

  • Rust 中动态大小类型的常规用法:他们有一些额外的元信息来储存动态信息的大小
  • 动态大小类型的黄金规则:必须将动态大小类型的值置于某种指针之后
  • Sized trait 来决定一个类型的大小是否在编译时可知;这个 trait 自动为编译器在编译时就知道大小的类型实现;另外,Rust 隐式的为每一个泛型函数增加了 Sized bound

在这里插入图片描述

20.4 高级函数与闭包

20.4.1 函数指针

  • 函数指针(function pointer):通过函数指针允许使用函数作为另一个函数的参数函数满足类型 fn(小写的 f),不要与闭包 trait 的 Fn(大写)相混淆
  • 不同于闭包,fn 是一个类型而不是一个 trait,所以直接指定 fn 作为参数而不是声明一个带有 Fn 作为 trait bound 的泛型参数
  • 函数指针实现了所有三个闭包 trait(FnFnMutFnOnce,所以总是可以在调用期望闭包的函数时传递函数指针作为参数

在这里插入图片描述
在这里插入图片描述

20.4.2 返回闭包

在这里插入图片描述

20.5 宏

20.5.1 宏和函数的区别

  • 从根本上来说,宏是一种为写其他代码而写代码的方式,即所谓的 元编程(metaprogramming)
  • 宏与函数的区别,如下 3 点
  • 宏能够接收不同数量的参数,但函数签名必须声明函数参数个数和类型
  • 在一个文件里调用宏 之前 必须定义它,或将其引入作用域;而函数则可以在任何地方定义和调用
  • 宏定义通常要比函数定义更难阅读、理解以及维护

在这里插入图片描述
在这里插入图片描述

20.5.2 macro_rules! :声明宏用于通用元编程

在这里插入图片描述
在这里插入图片描述

20.5.3 用于从属性生成代码的过程宏

在这里插入图片描述

20.5.4 如何编写自定义 derive 宏

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

20.5.5 类属性宏

  • 自定义派生宏derive 属性生成代码,derive 只能用于结构体和枚举
  • 类属性宏:类属性宏与自定义派生宏相似,能创建新的属性,属性还可以用于其它的项(比如:函数),也更为灵活

在这里插入图片描述

20.5.6 类函数宏

  • 类函数(Function-like)宏:定义看起来像函数调用的宏,类似于 macro_rules!,它们比函数更灵活(例如,可以接受未知数量的参数)

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值