网站的打开速度,福州建网站,做网页,十大免费数据网站,wordpress固定连接只能访问首页喜欢的话别忘了点赞、收藏加关注哦#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵#xff01;(#xff65;ω#xff65;)
15.3.1. 函数和方法的隐式解引用转化(Deref Coercion)
隐式解引用转化(Deref Coercion)是为函数和方法提供的一种便捷特性。
它的原理是…喜欢的话别忘了点赞、收藏加关注哦对接下来的教程有兴趣的可以关注专栏。谢谢喵(ω)
15.3.1. 函数和方法的隐式解引用转化(Deref Coercion)
隐式解引用转化(Deref Coercion)是为函数和方法提供的一种便捷特性。
它的原理是*假如类型T实现了Deref trait那么Deref Coercion可以把T的引用转化为T经过Deref操作后生成的引用。
当某类型的引用传递给函数或者是方法时但它的类型与定义的参数类型不匹配Deref Coercion就会自动发生。编译器会对deref进行一系列的调用来把它转换为所需的参数类型。这个操作在编译时完成没有额外的性能开销。
这句话比较绕看个例子就明白了。我们接着上篇文章的代码来写
use std::ops::Deref; struct MyBoxT(T); implT MyBoxT { fn new(x: T) - MyBoxT { MyBox(x) }
} implT Deref for MyBoxT { type Target T; fn deref(self) - T { self.0 }
}这是上篇文章的代码定义了MyBox元组结构体元组结构体的介绍详见 5.1. 定义并实例化struct创建了new函数并为其实现了Deref trait所以就可以使用一般的解引用操作来处理MyBox。
以下是增添的部分:
fn hello(name: str) { println!(Hello, {}, name);
}hello这个函数接收str也就是字符串切片类型然后打印出来。
写主函数看看实际使用
fn main(){ let m MyBox::new(String::from(Rust)); hello(m);
}m是MyBoxString类型m就是MyBoxString而hello函数接收的是str但这么写并不会报错这是为什么呢
首先MyBox已经实现了Deref trait所以Rust可以调用deref方法来把MyBoxString转化为String这就是刚才讲的那个比较绕的规则。
到这一步还没完String类型与str类型不同又是怎么转换的呢因为String类型也实现了Deref trait而且它的deref实现是返回一个字符串切片str类型所以Rust会在String上使用deref把String转化为str。最终这个类型就匹配了。
而如果Rust没有Deref Coercion那么写法会是
hello((*m)[..]);先使用解引用符号*把m从MyBoxString转化为String加上引用符号把m从String转化为String通过切片操作 [..]可以获得 String 中的完整内容的引用并且把其值从String转化为str
15.3.2. 解引用于可变性
可以使用DerefMut trait重载可变引用的*运算符。DerefMut相比Deref多了Mut这是指DerefMut返回的是可变引用mut T而Deref返回的是不可变引用T。
在类型和trait满足下列三种情况时Rust会执行Deref Coercion 当T:DerefTargetU允许T转换为U T实现了Deref trait而Deref trait下的deref方法的返回类型是U,那么T就可以被转化为U。 举个例子上文代码例的MyBox类型就实现了Deref trait其deref方法的返回值是泛型参数T所以MyBox就可以转换为T。 当T:DerefMutTargetU允许mut T转换为mut U。 T实现了DerefMut trait(DerefMut返回的是可变引用mut T)而DerefMut trait下的deref方法的返回类型是mut U,那么mut T就可以被转化为mut U。 当T:DerefTargetU,允许mut T转化为U。 Rust可以自动地把一个可变引用转化为不可变引用但是反过来绝对不行。因为将不可变的引用转化为可变的引用要求引用是唯一的借用规则中有讲详见 4.4. 引用与借用。