Smart pointers
Smart pointers allow you to store data on the heap rather than the stack. What remains on the stack is the pointer to the heap data.
Box<T>
for allocating values on the heapRc<T>
, a reference counting type that enables multiple ownershipRef<T>
andRefMut<T>
, accessed throughRefCell<T>
, a type that enforces the borrowing rules at runtime instead of compile time
Using Deref
trait to auto dereference
use std::ops::Deref;
struct MySmartPointer<T>{hold: T}
impl<T> MySmartPointer<T> {
fn new(hold: T) -> MySmartPointer<T> {
MySmartPointer{hold}
}
}
impl<T> Deref for MySmartPointer<T> {
type Target = T;
fn deref(&self) -> &T {
&self.hold
}
}
// using it
struct User {
name: &'static str
}
impl User {
fn print_name(&self) {
println!("My name is {}", self.name);
}
}
fn main() {
let user_pointer = MySmartPointer::new(User {name: "Alex"});
user_pointer.print_name(); // auto deref
}
Using Box
for unknown size type
#[derive(Debug)]
enum List {
Cons(i32, List),
Nil,
}
use crate::List::{Cons, Nil};
fn main() {
let list = Cons(1, Cons(2, Cons(3, Nil)));
println!("{:?}", list);
// recursive type has infinite size, won't compile
}
Above code won't compile as Rust cannot know the size of a List
as it is recursive. Now we can use Box<>
to make it's size known at compile time.
#[derive(Debug)]
enum List {
Cons(i32, Box<List>),
Nil,
}
use crate::List::{Cons, Nil};
fn main() {
let list = Cons(1,
Box::new(Cons(2,
Box::new(Cons(3,
Box::new(Nil))))));
println!("{:?}", list);
}