blob: 994394ca44b4d7bf58c0730866706f41229230be [file] [log] [blame] [view] [edit]
# Smart Pointers
A _pointer_ is a general concept for a variable that contains an address in
memory. This address refers to, or points at,” some other data. The most common
kind of pointer in Rust is a reference, which you learned about in Chapter 4.
References are indicated by the `&` symbol and borrow the value they point to.
They dont have any special capabilities other than referring to data, and have
no overhead.
_Smart pointers_, on the other hand, are data structures that act like a pointer
but also have additional metadata and capabilities. The concept of smart
pointers isnt unique to Rust: smart pointers originated in C++ and exist in
other languages as well. Rust has a variety of smart pointers defined in the
standard library that provide functionality beyond that provided by references.
To explore the general concept, well look at a couple of different examples of
smart pointers, including a _reference counting_ smart pointer type. This
pointer enables you to allow data to have multiple owners by keeping track of
the number of owners and, when no owners remain, cleaning up the data.
Rust, with its concept of ownership and borrowing, has an additional difference
between references and smart pointers: while references only borrow data, in
many cases, smart pointers _own_ the data they point to.
Though we didnt call them as such at the time, weve already encountered a few
smart pointers in this book, including `String` and `Vec<T>` in Chapter 8. Both
these types count as smart pointers because they own some memory and allow you
to manipulate it. They also have metadata and extra capabilities or guarantees.
`String`, for example, stores its capacity as metadata and has the extra ability
to ensure its data will always be valid UTF-8.
Smart pointers are usually implemented using structs. Unlike an ordinary struct,
smart pointers implement the `Deref` and `Drop` traits. The `Deref` trait allows
an instance of the smart pointer struct to behave like a reference so you can
write your code to work with either references or smart pointers. The `Drop`
trait allows you to customize the code thats run when an instance of the smart
pointer goes out of scope. In this chapter, well discuss both traits and
demonstrate why theyre important to smart pointers.
Given that the smart pointer pattern is a general design pattern used frequently
in Rust, this chapter wont cover every existing smart pointer. Many libraries
have their own smart pointers, and you can even write your own. Well cover the
most common smart pointers in the standard library:
* `Box<T>` for allocating values on the heap
* `Rc<T>`, a reference counting type that enables multiple ownership
* `Ref<T>` and `RefMut<T>`, accessed through `RefCell<T>`, a type that enforces
the borrowing rules at runtime instead of compile time
In addition, well cover the _interior mutability_ pattern where an immutable
type exposes an API for mutating an interior value. Well also discuss
_reference cycles_: how they can leak memory and how to prevent them.
Lets dive in!