解引用的trait

实现Deref trait允许我们重载解引用运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//前提: A类型必须实现解引用 Deref trait
let a: A = A::new();
let b = &a;
let c = *b;

fn main()
{
let x = 5; //数据在栈上
let y = &x;
assert_eq!(5,x);
assert_eq!(5,*y); //解引用

//Box实现了解引用
let z = Box::new(x); //由于使用x对象,所以使用x的copy属性,这个数据是在栈上

assert_eq!(5,*z);//因为实现了Deref trait所以可以像普通引用一样使用。

}

解引用Deref trait的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
use std::ops::Deref;
struct MyBox<T>(T);

impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T; //固定写法,在标准函数文档中有解释
fn deref(&self) -> &T {
&self.0 //不希望获得T的所有权,只是想返回它的引用
}
}
fn main() {
let x = 5;
let y = MyBox::new(x);

assert_eq!(5,x);
assert_eq!(5,*y);//需要实现解引用Deref

}

解引用的强制多态

Deref为String实现了强制多态,在使用&String的时候,强制多态转换为&str
解引用多态和可变性的交互:

  1. 当T:Deref<Target=U>时,从&T到&U
  2. 当T: DerefMut<Target=U>时,从&mut T到&mut U
  3. 当T: Deref<Target=U>时,从&mut T到& U
  • &T->&U
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
use std::ops::Deref;
struct MyBox<T>(T);

impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T; //固定写法,在标准函数文档中有解释
fn deref(&self) -> &T {
&self.0 //不希望获得T的所有权,只是想返回它的引用
}
}

fn hello(name: &str) {
println!("Hello, {}",name);
}
fn main() {
let m = MyBox::new(String::from("Rust"));
hello(&m); //这里需要解释的是:
//m是一个string,但是函数需要的是一个&str
//将MyBox变为&String,之后会调用标准库里边String的解引用,变为字符串slice
//实际上变成了&str
}