Rust常用特型之Deref和DerefMut特型

在Rust标准库中,存在很多常用的工具类特型,它们能帮助我们写出更具有Rust风格的代码。

你可以通过在你的类型上实现std::ops::Derefstd::ops::DerefMut特型来自定义解引用操作例如*操作符和.操作符的行为。像Box<T>Rc<T>实现了这两个特型,所以他们的行为就像Rust内置指针类型一样。例如,如果你有一个Box<Complex>类型的值b,此时,*b 代表的是b指向的那个复数值。b.re代表该复数的实部.

如果对引用赋值或者借借出一个可变引用,那么Rust使用DerefMut特型。否则,只读就足够了,此时会使用Deref特型。

这两个特型的定义类似如下:

trait Deref {
   
   
  type Target: ?Sized;
  fn deref(&self) -> &Self::Target;
}
trait DerefMut: Deref {
   
   
  fn deref_mut(&mut self) -> &mut Self::Target;
}

derefderef_mut函数都使用&self引用作为参数并且返回一个&Self::Target的引用。 Target是该类型所拥有的,包含的或者指向的一个具体变量类型(显然,它不可能把它不知道的东西借出去,例如另一个结构体中的字段)。例如对Box<Complex>来说,这里的Target就是Complex。注意DerefMut拓展了Deref,这时显而易见的,如果你能解引用并修改它,那么你肯定能借出一个共享的引用而不修改。因为函数返回的引用的生命周期和&Self相同(生命周期三原则),只要函数返回的引用一直存在,那么Self本身就一直被借用。其实这里说的是只要是&Self有效,那么函数得到的引用就一直有效。

DerefDerefMut特型同时还扮演了其它角色。由于deref函数拿走了一个&Self引用但是返回了一个&Self::Target引用,Rust可以使用它来进行自动引用转换,将&Self转换成&Self::Target。换句话说,如果插入一个deref函数能消除类型不匹配的语法错误,Rust会自动为你插入。DerefMut也可以作相应的转换,只不过是可变引用。这个功能叫着deref coericoins(强制解引用),一个类型被强制表现为另一种类型。

尽管你也可以自己写一个类似强制转引用的功能,但是它们很方便:

  • 如果你有一个Rc<String>类型的值r,你想在它上面应用String::find函数,你可以简单的写成r.find(?),而不是(*r).find(?)。这是因为这个find函数调用隐式的借用r, 而Rc<T>实现了Deref<Target=T>,因此&Rc<String> 可以被解引用为&String.其实这里就是智能指针的应用(可以把智能指针当成普通内置指针使用)

  • 你可以在String上使用split_at函数,虽然该函数是定义在str字符串切片类型上的,因为String实现了Deref<Target=str>String并不需要重新实现split_at函数,因为你可以从&String强制解引用得到&str。 这里其实是Rust中的一个便利性,我们可以在非常底层的数据结构上定义函数,然后其它结构可以直接使用。最常见的就是Vec<T>,其绝大部分函数是定义在切片[T]上的,但是因为强制解引用,你可以非常简单的直接在向量上使用这些函数。我们看一下代码直观就更明显:

    impl str {
         
         
        pub const fn len(&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AiMateZero

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值