A smart pointer in Rust - Box<T>

Rust also has a smart pointer type with unique ownership called Box<T>. Putting a value on the heap can be done through Box<T> in a number of ways:

fn main() {
    let b1: Box<i32> = Box::new(42);

    let on_stack: i32 = 43;
    let b2: Box<i32> = on_stack.into();
    let back_on_stack: i32 = *b2;

    let boxed_array: Box<[i32]> = Box::new([1, 2, 3]);

    let deep_copied: Box<i32> = b1.clone();
}

Run this example

What is interesting is that Box<T> allows copying, whereas std::unique_ptr<T> did not allow copying. Rust actually does something smart here: Remember that Rust provides the Clone trait for values that have non-trivial copy operations? Well in Rust we can implement a trait on a type conditionally, like so:

#![allow(unused)]
fn main() {
impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
    fn clone(&self) -> Self {
        //... clone implementation
    }
}
}

Ignoring the A generic type for now, this statement implements the Clone trait for Box<T> only if T implements the Clone trait! This is a common pattern in Rust to propagate specific behaviour from a wrapped type (e.g. T) to its wrapper (e.g. Box<T>). Box<T> has a lot of these conditional trait implementations to make Box<T> behave like T in most situations. For example, we can test two instances of Box<T> for equality if T can be tested for equality (which is realized through the Eq trait):

pub fn main() {
    let b1: Box<i32> = Box::new(42);
    let b2: Box<i32> = Box::new(42);

    println!("{}", b1 == b2);
}

Run this example

b1 and b2 are located at different memory addresses, but their values are equal, so b1 == b2 resolves to true.

There is not much more to say about Box<T> at this point, besides that it is the main way of getting stuff on the heap in Rust. Let's move on to something more interesting then!