Les pointeurs intelligents
Un pointeur est un concept général pour une variable qui contient une adresse en mémoire. Cette adresse fait référence, ou “pointe vers”, d’autres données. Le type de pointeur le plus courant en Rust est une référence, que vous avez découverte au chapitre 4. Les références sont indiquées par le symbole & et empruntent la valeur vers laquelle elles pointent. Elles n’ont pas de capacités particulières autres que de faire référence à des données, et elles n’ont aucun surcoût.
Les pointeurs intelligents (smart pointers), en revanche, sont des structures de données qui agissent comme un pointeur mais possèdent également des métadonnées et des capacités supplémentaires. Le concept de pointeurs intelligents n’est pas propre à Rust : les pointeurs intelligents sont apparus en C++ et existent également dans d’autres langages. Rust dispose d’une variété de pointeurs intelligents définis dans la bibliothèque standard qui fournissent des fonctionnalités au-delà de celles offertes par les références. Pour explorer le concept général, nous examinerons quelques exemples différents de pointeurs intelligents, notamment un type de pointeur intelligent à comptage de références. Ce pointeur vous permet de donner plusieurs propriétaires à des données en suivant le nombre de propriétaires et, lorsqu’il n’en reste plus aucun, en nettoyant les données.
En Rust, avec son concept de possession et d’emprunt, il existe une différence supplémentaire entre les références et les pointeurs intelligents : alors que les références ne font qu’emprunter des données, dans de nombreux cas les pointeurs intelligents possèdent les données vers lesquelles ils pointent.
Les pointeurs intelligents sont généralement implémentés à l’aide de structs. Contrairement à une struct ordinaire, les pointeurs intelligents implémentent les traits Deref et Drop. Le trait Deref permet à une instance de la struct du pointeur intelligent de se comporter comme une référence afin que vous puissiez écrire du code qui fonctionne avec des références ou des pointeurs intelligents. Le trait Drop vous permet de personnaliser le code qui s’exécute lorsqu’une instance du pointeur intelligent sort de la portée. Dans ce chapitre, nous aborderons ces deux traits et montrerons pourquoi ils sont importants pour les pointeurs intelligents.
Étant donné que le patron de pointeur intelligent est un patron de conception général fréquemment utilisé en Rust, ce chapitre ne couvrira pas tous les pointeurs intelligents existants. De nombreuses bibliothèques ont leurs propres pointeurs intelligents, et vous pouvez même écrire les vôtres. Nous couvrirons les pointeurs intelligents les plus courants de la bibliothèque standard :
Box<T>, pour allouer des valeurs sur le tasRc<T>, un type à comptage de références qui permet la possession multipleRef<T>etRefMut<T>, accessibles viaRefCell<T>, un type qui applique les règles d’emprunt à l’exécution plutôt qu’à la compilation
De plus, nous couvrirons le patron de mutabilité intérieure où un type immuable expose une API pour modifier une valeur intérieure. Nous aborderons également les cycles de références : comment ils peuvent provoquer des fuites de mémoire et comment les éviter.
Plongeons-nous dans le sujet !