Course contentsShow
← Rust
Lesson 735 of 1,9106. Generics and Static DispatchFree lesson

Implementing Custom Smart Pointers

Create generic container types that extend the functionality of standard smart pointers.

In this lesson, you will learn how to create your own generic wrapper types that manage resource lifetimes and access, effectively building your own smart pointers.

Extending Smart Pointer Functionality

A "smart pointer" in Rust is essentially a struct that holds a value and implements the Deref and Drop traits. When we make these structures generic, we gain the ability to create wrappers that behave like Box<T> or Rc<T> but provide custom behavior, such as logging access, adding metadata, or enforcing unique initialization rules.

Building a Generic Logger Pointer

To implement a custom smart pointer, you define a generic struct and implement std::ops::Deref to provide transparent access to the inner data.

use std::ops::Deref;

struct LoggedPtr<T> {
    data: T,
}

impl<T> LoggedPtr<T> {
    fn new(data: T) -> Self {
        println!("Allocating data...");
        LoggedPtr { data }
    }
}

impl<T> Deref for LoggedPtr<T> {
    type Target = T;

    fn deref(&self) -> &T {
        println!("Accessing data!");
        &self.data
    }
}

By implementing Deref, your LoggedPtr<T> can now be treated exactly like a reference to T. When you call a method on the inner data, Rust automatically invokes deref(), allowing your custom logic to trigger without the user needing to call a special method.

The Role of RAII

Because you are managing the lifecycle of the inner value, you must also implement the Drop trait. This is where the RAII (Resource Acquisition Is Initialization) pattern comes into play: when your custom pointer goes out of scope, the compiler guarantees that your drop implementation will run, allowing you to clean up resources, close file handles, or log the deallocation process.

By combining Deref for transparent access and Drop for deterministic cleanup, you create a seamless generic container that feels like a native part of the language, despite being a custom implementation tailored to your specific system requirements.

Key Takeaway: Custom smart pointers leverage generic structs with Deref and Drop traits to inject custom behavior into the lifecycle and access patterns of any type T without changing the interface of the underlying data.