Rust的Deref coercion和自动解引用

最近对rust的自动解引用以及deref coercion有点懵。

1. Dereftrait重载*与Deref coercion

实现Dereftrait可以让我们将对应类型视为指针,该trait仅应当被实现在智能指针中。从而让访问智能指针指向的数据更加方便。

Deref中需要实现fn deref(&self) -> &T,该方法返回&T的原因是因为所有权机制下若返回T则对应move语义。

若x实现了Dereftrait,则rust编译器会将*x自动展开为*(x.deraf()),即首先转换为&T然后*&T,获取到对应值。

1.1. Deref coercion

在实现了Dereftrait后,编译器在某些情况下会自动通过Deref::deref()将某些类型转换为对另一种类型的引用。该情况具体如下:

向函数传引用,然而该引用的类型和该函数/方法的参数的类型不同。

&String自动转换成&str,若没有该机制,则需要实现为&(*m)[..]

2. .运算符与自动解引用

当使用.运算符时,rust编译器会插入尽可能多的*。例如:

1
2
3
4
5
6
let mut name: String = "hello".to_string();
let name_ref: &String = &name;
// len()是String的方法。这里使用了auto deref,以获得String。
let name_len = name_ref.len();
// 等价于
let name_len = (*name_ref).len();

2.1. Deref和自动解引用

由于实现了Dereftrait的类型的引用能够让编译器处理*x自动调用deref()方法*(x.deref())。而自动解引用的时候会自动插入*。因而,这两种可能会共同起作用,如下:

1
2
let vec = vec![1, 2, 3];
let iterator = vec.iter();

这里iter()[T]实现的方法。真正的转换情况是,编译器插入*vec.iter(),然后对应*(vec.deref()).iter(),然后对应*(&[T].iter(),即[T].iter()