Rust Deref trait

Deref <T> trait用于自定义解除引用运算符(*)的行为。
如果实现Deref <T>特征,则可以将智能指针视为参考。 因此,在引用上工作的代码也可以用在智能指针上。

常规引用

常规引用是一种指向某个值的指针,该值存储在其他地方。下面来看一个简单的例子来创建i32类型值的引用,然后使用引用运算符和this引用。

fn main()
{
  let a = 20;
  let b = &a;
  if a==*b
  {
    println!("a and *b are equal");
  }  

  else
  {
    println!("they are not equal");
  }
}Rust

执行上面示例代码,得到以下结果 -

a and *b are equalShell

在上面的例子中,a保存i32类型值20,而b包含a变量的引用。 如果使用* b,那么它代表值20。因此,可以比较变量a* b,它将返回真值。 如果使用&b而不是* b,则编译器会抛出错误“无法将{integer}与{&integer}进行比较”。

Box <T>作为引用

Box <T>指针可用作引用。

下面来看一个简单的例子:

fn main()
{
  let a = 11;
  let b = Box::new(a);
  print!("Value of *b is {}",*b);
}Rust

输出结果如下所示 -

Value of *b is 11Shell

在上面的示例中,Box <T>的行为与常规引用类似。 它们之间的唯一区别是b包含指向数据的框,而不是通过使用&运算符引用该值。

智能指针作为引用

现在,创建类似于Box <T>类型的智能指针,它们的行为与常规引用有一些不同。

Box <T>可以定义为具有一个元素的元组结构,例如MyBox <T>
创建元组结构后,在MyBox <T>类型上定义函数。

下面来看一个简单的例子:

struct MyBox<T>(T);
impl<T> MyBox<T>
{
  fn example(y : T)->MyBox<T>
  {
    MyBox(y)
  }
}
fn main()
{
  let a = 8;
  let b = MyBox::example(a);
  print!("Value of *b is {}",*b);
}Rust

执行上面示例代码,得到以下结果 -

在上面的例子中,创建了智能指针b,但它不能被解除引用。 因此得出结论,无法取消类似于Box <T>类型的自定义指针的引用。

实现Deref Trait

  • Deref Trait在标准库中定义,该库用于实现名为deref的方法。

  • deref方法借用self并返回对内部数据的引用。

下面来看一个简单的例子:

struct MyBox<T>
{
  a : T,
}
use :: std::ops::Deref;
impl<T> Deref for MyBox<T>
{
  type Target = T;
  fn deref(&self) ->&T
  {
    &self.a
  }
}
fn main()
{
  let b = MyBox{a : 10};
  print!("{}",*(b.deref()));
}Rust

执行上面示例代码,得到以下结果 -

10Shell

程序说明

  • Deref traitMyBox类型上实现。

  • Deref trait实现deref()方法,deref()方法返回a变量的引用。

  • type Target = T;Deref trait的关联类型。关联类型用于声明泛型类型参数。

  • 创建了MyBox类型的实例 - b

  • 通过使用MyBox类型的实例b.deref()调用deref()方法,然后取消引用从deref()方法返回的引用。

Deref强制

  • Deref强制是将实现Deref trait的引用转换为Deref可以将原始类型转换为的引用的过程。

  • Deref强制是对函数和方法的参数执行的。

  • 当将特定类型的引用传递给与函数定义中的参数类型不匹配的函数时,Deref强制自动发生。

下面来看一个简单的例子:

struct MyBox<T>(T);
use :: std::ops::Deref;
impl<T> MyBox<T>
{
  fn hello(x:T)->MyBox<T>
  {
    MyBox(x)
  }
}
impl<T> Deref for MyBox<T>
{
  type Target = T;
  fn deref(&self) ->&T
  {
    &self.0
  }
}
fn print(m : &i32)
{
  print!("{}",m);
}
fn main()
{
  let b = MyBox::hello(5);  

  print(&b);
}Rust

执行上面示例代码,得到以下结果 -

5

在上面的例子中,使用参数&b调用print(&b)函数,它是&Box <i32>的引用。 在这种情况下,实现Deref trait,通过Deref强制过程将&Box <i32>转换为&i32

Derif强制与可变性的相互作用

到目前为止,使用Deref Trait覆盖不可变引用上的*运算符,可以使用DerefMut Trait覆盖可变引用上的*运算符。

Rust在以下三种情况下执行Deref强制:

  • 当T:Deref <Target = U>其中TU是不可变引用时,则&T转换为&U类型。

  • 当T:DerefMut <Target = U>,其中TU是可变引用时,则&mut T被转换为&mut U

  • 当T:Deref <Target = U>,其中T是可变引用而U是不可变引用,则&mut T被转换为&U

(0)

相关推荐

  • use关键字在PHP中的几种用法

    use关键字在PHP中的几种用法 在学习了和使用了这么多年的PHP之后,您知道use这个关键字在PHP中都有哪些用法吗?今天我们就来看一下它的三种常见用法. 1. 用于命名空间的别名引用 // 命名空 ...

  • 2021第一季度开发者报告新鲜出炉,最流行的编程语言居然是它?

    近日,开发者调查分析公司SlashData发布了2021年<开发者报告>(第20版).报告中掺杂着大量冰冷的数字,无情的叙述,让我们的程序员同学看起来一点都不活泼了. SlashData的 ...

  • Rust 语言风靡学术界

    AWS 将 Rust 编译器团队负责人收入麾下的新闻让开发者们再次聚焦于这门兼具安全性与高性能的编程语言.近日,著名科学期刊 Nature 刊登了一篇文章,表明 Rust 语言也正在成为学术界最受欢迎 ...

  • Rust基础学习笔记(零):复习基本知识

    由于一个学期没有碰Rust,相关知识殆已忘尽.最近各课逐渐停授,余出时间来从基础重温这些知识,也算是对没有写的基础知识的补充.另外这次复习主要参照了Youtube上的Crush Course视频,两个 ...

  • Rust Drop trait

    drop trait用于在值超出范围时释放文件或网络连接等资源. drop trait用于释放Box <T>指向的堆上的空间. drop trait用于实现drop()方法,该方法对sel ...

  • (40条消息) 基于腾讯云的 Rust 和 WebAssembly 函数即服务

    腾讯云云函数 (SCF) 已经支持十多种编程语言和运行时框架.腾讯云最近发布的 SCF custom runtime(自定义运行时)更进一步 -- SCF 现在可以支持用任何编程语言编写的函数. 本文 ...

  • 报告:JavaScript 开发者达1380 万,C#超越 PHP,Rust 增长最快

    出品|开源中国 文|白开水 研究公司 SlashData 最新发布的"State of the Developer Nation"第 20 版报告指出,全球开发者社区在过去六个月中 ...

  • 揭秘全球开发最新趋势!JS开发者达1380万,C#超越PHP,Rust增长最快

    白开水 OSC开源社区 昨天 文 | 白开水 出品 | OSC开源社区(ID:oschina2013) 研究公司 SlashData 最新发布的"State of the Developer ...

  • C 和 C 不安全?Android 支持 Rust 开发操作系统

    Rust这两年实火了. 近年来,Rust凭借着出色的内存效率.速度与安全性,深受亚马逊.微软.华为.Facebook等科技巨头的青睐.Rust从根本上考虑安全性,提出了"没有数据竞争的并发性 ...

  • Deno 1.0 发布了,它用 Rust 写就

    官网:https://deno.land/ 作为开发发 Node.js 的大神程序员 Ryan,最近又推出了一个新的框架叫做 Deno,它的名字简写自 Destroy Node.从名字上就可以看出来, ...

  • trait能力在PHP中的使用

    trait能力在PHP中的使用 相信大家对trait已经不陌生了,早在5.4时,trait就已经出现在了PHP的新特性中.当然,本身trait也是特性的意思,但这个特性的主要能力就是为了代码的复用. ...

  • [PHP小课堂]trait能力在PHP中的使用

    [PHP小课堂]trait能力在PHP中的使用 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[xiaoyuezigonggong/149844827]免费得PHP.项目管理学习资料 ...

  • Linux 之父:我们不会用 Rust 取代 C 语言开发内核

    Linux 诞生于 1991 年,距今已经 30 年了.虽然它一开始只是 Linus 的一个个人项目,而非出于要开发一个新操作系统的伟大梦想,但如今的 Linux 早已无处不在. 30 年前,当 Li ...