Smart pointers implement the Deref
and Drop
traits. The Deref
trait allows an instance of the smart pointer struct to behave like a reference so you can write code that works with either references or smart pointers. The Drop
trait allows you to customize the code that is run when an instance of the smart pointer goes out of scope.
Box<T>
is mostly used in following situations:
One must implement Deref
for a custom type to enable dereferencing on the type.
use std::ops::Deref;
struct MyBox<T>(T); // tuple struct of generic type T
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
// This impl is needed for below dereferencing of y
impl<T> Deref for MyBox<T> {
type Target = T; // associated type
// deref must borrow self and return a reference to the inner data.
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn main() {
let x = 5;
let y = MyBox::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
Once Deref
is implemented, one can treat the type as a reference, and benefit from deref coercion.
Assume we have a function like this:
fn func(name: &str) {
// do sth with name
}
With deref coercion, we can make function calls with reference parameters a lot easier to read and write, like below:
fn main() {
let m = MyBox::new(String::from("Rust"));
func(&m); // &MyBox<String> ==> &String ==> &str
}
If Rust did not have deref coercion, we would need to:
fn main() {
let m = MyBox::new(String::from("Rust"));
func(&(*m)[..]);
}
Deref coercion will only be possible in three cases:
&T
to &U
when T: Deref<Target=U>
&mut T
to &mut U
when T: DerefMut<Target=U>