Smart Pointers in Rust

Table of Contents

Smart Pointers in Rust

Boxes

It's useful for:

Usage

use std::box::Box;

fn main() {
    let b = Box::new(5);
    dbg!(b);
}

Rc (Reference Counted Box)

Rc is used for types where there are multiple owners. As such, cloning it increments the reference count, while dropping it decreases the reference count.

It is automatically dropped at the end of its scope, or you can explicitly drop it.

enum List {
    Cons(i32, Rc<List>),
    Nil,
}

use crate::List::{Cons, Nil};
use std::rc::Rc;

fn main() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    println!("count after creating a = {}", Rc::strong_count(&a)); // 1
    let b = Cons(3, Rc::clone(&a));
    println!("count after creating b = {}", Rc::strong_count(&a)); // 2
    {
        let c = Cons(4, Rc::clone(&a));
        println!("count after creating c = {}", Rc::strong_count(&a)); // 3
    }
    let d = Cons(3, Rc::clone(&a));
    println!("count after creating d = {}", Rc::strong_count(&a)); // 3
    drop(d); // drop d
    println!("count after dropping d = {}", Rc::strong_count(&a)); // 2
    println!("count after c goes out of scope = {}", Rc::strong_count(&a)); // 2
}

RefCell

Refcell allows mutable borrows checked at runtime. You can mutate the value inside a Refcell<T> even if it is labeled as immutable.

You can use Refcell with Rc to have multiple owners of data.

#[derive(Debug)]
enum List {
    Cons(Rc<RefCell<i32>>, Rc<List>),
    Nil,
}

use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let value = Rc::new(RefCell::new(5));

    let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil))); // a is 5, the tail of the list.

    let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a)); // b is a list of 3 -> a
    let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a)); // c is a list of 4 -> a

    *value.borrow_mut() += 10; // add 10 to the tail of the list, a.

    println!("a after = {:?}", a);
    println!("b after = {:?}", b);
    println!("c after = {:?}", c);
}