# The Rust Programming Language
# Smart Pointers
# Deref
*
sign can only deference &
. So if we define a custom smart pointer, we have to implement the Deref
trait so that *
knows how to get the &
reference from the smart pointer.
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) -> &Self::Target {
&self.0
}
}
fn main() {
let x = 6;
let y = MyBox::new(x);
assert_eq!(6, *y);
}
Behind the scene, when rust runs *y
, it runs *(y.deref())
.
# Coercion
&String
can automatically get coerced to &str
because String
implements the Deref
trait that returns &str
.
fn hello(name: &str) {
println!("Hello {name}");
}
fn main() {
let m = MyBox::new(String::from("Rust"));
hello(&m);
}
Here &m
automatically converts &Mybox<String>
to &String
by calling deref()
. Then rust will call String
's deref()
to convert &String
into &str
.
So &m
is equal to &(*m)[..]
where *m
converts it to String
, &String[..]
takes a string slice of the String
that is equal to the whole string.
# Concurrency
# Send
and Sync
Send
marker trait indicates that ownership of values of hte type implementing Send
can be transferred between threads.
Sync
marker trait indicates that it is safe for the type implementing Sync
to be reference from multiple threads. In other words, any type T
is Sync
if &T
(an immutable reference to T
) is Send
.