【Rust自学】15.3. Deref trait Pt.2:隐式解引用转化与可变性

发布时间:2026/7/23 18:58:38
【Rust自学】15.3. Deref trait Pt.2:隐式解引用转化与可变性 15.3 Deref trait Pt.2隐式解引用转化与可变性15.3.1 函数和方法的隐式解引用转化隐式解引用转化deref coercion是为函数和方法提供的一种便捷特性。它的原理是假如类型T实现了Dereftrait那么解引用转化可以把T的引用转换成对T应用Deref之后得到的引用。当某个类型的引用被传给函数或方法但其类型与声明的参数类型不匹配时解引用转化会自动发生。编译器会对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函数并为其实现了Dereftrait因此可以对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已经实现了Dereftrait所以 Rust 可以调用deref把MyBoxString转换成String。这就是刚才那个比较抽象的规则。到这一步还没完。String和str是不同的类型那又是怎么转换的呢因为String也实现了Dereftrait而且它的deref实现返回的是str类型的字符串切片所以 Rust 会对String使用deref把String转换成str。最终类型就匹配了。如果 Rust 没有解引用转化写法会是这样hello((*m)[..]);先使用解引用运算符*把m从MyBoxString转换成String。再加上引用符号把String转换成String。通过切片语法[..]可以获得String完整内容的引用并将其值从String转换成str。15.3.2 解引用与可变性可以使用DerefMuttrait 来重载可变引用的*运算符。与Deref相比DerefMut多了Mut意思是DerefMut返回可变引用mut T而Deref返回不可变引用T。当类型和 trait 满足下列三种情况时Rust 会执行解引用转化- 当T: DerefTarget U时T可以转换成UT实现了Dereftrait且Deref下deref的返回类型是U因此T可以转换成U。例如上文代码中的MyBox类型实现了Deref其deref方法返回T所以MyBox可以转换成T。当T: DerefMutTarget U时mut T可以转换成mut U。T实现了DerefMuttraitDerefMut返回可变引用mut T且DerefMut下deref的返回类型是mut U因此mut T可以转换成mut U。当T: DerefTarget U时mut T可以转换成U。Rust 可以自动地把可变引用转换成不可变引用但反过来绝对不行。把不可变引用转换成可变引用要求该引用是唯一的借用规则中有讲详见 4.4. 引用与借用。