Todayโs learning was all about treating smart pointers like regular references by implementing the Deref trait, exploring deref coercion, and understanding how it interacts with mutability.
๐ Following References to Values
A regular reference (&T) points to a value stored elsewhere. To access the value, we use the dereference operator *:
fn main() {
let x = 5;
let y = &x;
assert_eq!(5, x);
assert_eq!(5, *y);
}
Here *y follows the reference to get the value 5. Without *, the comparison wonโt compile because {integer} and &{integer} are different types.
๐ฆ Using Box Like a Reference
Smart pointers like Box<T> behave similarly to references when dereferenced:
fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
๐ Defining Our Own Smart Pointer
We can define our own smart pointer MyBox<T>:
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x: T) -> MyBox<T> {
MyBox(x)
}
}
But trying to dereference *y will fail until we implement the Deref trait.
๐ Implementing the Deref Trait
To enable dereferencing:
use std::ops::Deref;
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
Now *y works just like with Box<T>.
Behind the scenes:
*(y.deref())
This happens automatically whenever we use *.
๐ Implicit Deref Coercions
Deref coercion allows automatic conversion between references:
- From
&Tto&UwhenT: Deref<Target=U> - From
&mut Tto&mut UwhenT: DerefMut<Target=U> - From
&mut Tto&UwhenT: Deref<Target=U>
Example with MyBox<String>:
fn hello(name: &str) {
println!("Hello, {name}!");
}
fn main() {
let m = MyBox::new(String::from("Rust"));
hello(&m); // Works because of deref coercion
}
Without coercion, weโd need:
hello(&(*m)[..]);
Much harder to read!
๐ Deref and Mutability
-
&T โ &Uworks withDeref. -
&mut T โ &mut Uworks withDerefMut. -
&mut T โ &Uis also allowed. - โ But
&T โ &mut Uis not allowed, because it could break Rustโs borrowing rules.
This ensures safety and prevents undefined behavior.
๐ง Summary
- Regular references require
*to access the value. -
Box<T>and custom smart pointers can implementDerefto behave like references. - Deref coercion simplifies function calls by automatically converting types.
- Mutability rules ensure safety: mutable โ immutable works, but immutable โ mutable does not.
Rustโs deref system is a zero-cost abstraction: all conversions happen at compile time with no runtime cost.
๐ Thatโs all for Day 28! Tomorrow, Iโll continue exploring more about **smart pointers and their advanced use
Top comments (0)