Deref
Deref
可以访问被分配的资源。
dereference 类似于 C++ 中的指针 *
操作符,并且只能在 &...
上或者实现了 Deref
trait 的类型上使用。仅引用类型的实参才会触发自动解引用
隐式 Deref
转换
Rust 编译器在碰到实参与形参的类型对不上的时候,会考虑将实参自动 Deref 以匹配函数的形参类型。考虑这样的代码:
1 | fn main() { |
s
的类型是 Box<String>
,而函数的形参类型是 &str
,出现对不上号的情况。于是 Rust 编译器做了如下的自动 dereference:
1 | Box<String> ==> &String ==> &str |
连续的 Deref
转换(引用归一化)
先前提到,Rust 只能对 &
进行 dereference,当遇到多个 &&&&&&
或者智能指针的时候,Rust 是怎么处理的呢?简而言之,可以概括为以下几点:
- 智能指针
Box<T>
展开成&T
(包括其他类型的智能指针,如Rc<T>, Arc<T>
) - 把多重
&&&&&
归一为单个&
第二点在标准库里是这样实现的:
1 | impl <T: ?Sized> Deref for &T { |
Deref
与 DerefMut
dereference 还支持将 mutable reference 转换成 immutable reference,或者 immutable reference 转换成 mutable reference.
- 当
T: Deref<Target=U>
时,&T
可以转换成&U
,immutable refimmutable ref - 当
T: Deref<Target=U>
时,&mut T
可以转换成&U
- 当
T: DerefMut<Target=U>
时,&mut T
可以转换成&mut U
并且,从标准库实现上说,DerefMut
是继承了 Deref
.
Drop
Drop
特征可以释放资源。在变量超出作用域的时候,执行一段特定的代码,最终编译器将帮助自动插入这段收尾代码。
当然也可以手动调用 xxx.drop()
进行手动回收。
Drop
的顺序
我们考察下面这段代码:
1 | struct HasDrop1; |
输出为
1 | Running! |
由此可以得出 drop 的顺序:
- 变量级别,按照逆序的方式,
_x
在_foo
之前创建,因此_x
在_foo
之后被 drop - 结构体内部,按照顺序的方式,结构体
_x
中的字段按照定义中的顺序依次 drop
Copy
与 Drop
互斥
我们无法为一个类型同时实现 Copy
和 Drop
特征。因为实现了 Copy
特征的类型会被编译器隐式的复制,因此非常难以预测析构函数执行的时间和频率。因此这些实现了 Copy
的类型无法拥有析构函数。