Smart Pointers
Un puntero es un concepto general para una variable que contiene una dirección
en memoria. Esta dirección se refiere, o “apunta a,” algún otro dato. El tipo
más común de puntero en Rust es una referencia, la cual aprendiste en el
Capítulo 4. Las referencias son indicadas por el símbolo &
y toman prestado
el valor al que apuntan. No tienen ninguna capacidad especial más allá de
referirse a datos, y no tienen sobrecarga.
Los Smart pointers, por otro lado, son estructuras de datos que actúan como un puntero, pero también tienen metadatos y capacidades adicionales. El concepto de smart pointers no es único de Rust: los smart pointers se originaron en C++ y existen en otros lenguajes también. Rust tiene una variedad de smart pointers definidos en la biblioteca estándar que proveen funcionalidad más allá de la proveída por las referencias. Para explorar el concepto general, veremos un par de ejemplos diferentes de smart pointers, incluyendo un tipo de puntero reference counting. Este puntero te permite permitir que los datos tengan múltiples propietarios al mantener un registro del número de propietarios y, cuando no hay propietarios restantes, limpiar los datos.
Rust, con su concepto de propiedad y préstamo, tiene una diferencia adicional entre referencias y smart pointers: mientras que las referencias solo toman prestado los datos, en muchos casos, los smart pointers son dueños de los datos a los que apuntan.
Aunque no los llamamos así en ese momento, ya hemos encontrado algunos smart
pointers en este libro, incluyendo String
y Vec<T>
en el Capítulo 8. Ambos
estos tipos cuentan como smart pointers porque poseen algo de memoria y te
permiten manipularla. También tienen metadatos y capacidades o garantías
adicionales. String
, por ejemplo, almacena su capacidad como metadato y tiene
la capacidad adicional de asegurar que sus datos siempre serán UTF-8 válidos.
Los smart pointers usualmente son implementados usando structs. A diferencia de
un struct ordinaria, los smart pointers implementan los traits Deref
y
Drop
. El trait Deref
permite que una instancia de la struct smart pointer se
comporte como una referencia, así que puedes escribir tu código para trabajar
con referencias o smart pointers. El trait Drop
te permite personalizar el
código que se ejecuta cuando una instancia del smart pointer sale del scope. En
este capítulo, discutiremos ambos traits y demostraremos por qué son
importantes para los smart pointers.
Dado que el patrón de smart pointer es un patrón de diseño general usado frecuentemente en Rust, este capítulo no cubrirá todos los smart pointers existentes. Muchas bibliotecas tienen sus propios smart pointers, e incluso puedes escribir los tuyos. Cubriremos los smart pointers más comunes en la biblioteca estándar:
Box<T>
para asignar valores en el heapRc<T>
, un tipo de conteo de referencias que permite múltiples ownershipsRef<T>
yRefMut<T>
, accedidos a través deRefCell<T>
, un tipo que impone las reglas de borrowing en tiempo de ejecución en lugar de tiempo de compilación
Además, cubriremos el patrón interior mutability donde un tipo inmutable expone una API para mutar un valor interior. También discutiremos reference cycles: cómo pueden fugar memoria y cómo prevenirlos.
¡Vamos a profundizar en los smart pointers!