Pointeurs intelligents en Rust
Les pointeurs intelligents sont une structure de données courante en Rust qui offrent des fonctionnalités supplémentaires et des garanties de sécurité pour aider à gérer la mémoire et les données.
En Rust, les pointeurs intelligents sont un type de données qui encapsule la gestion de la propriété et de la durée de vie de la mémoire allouée dynamiquement.
Les pointeurs intelligents encapsulent généralement un pointeur brut et fournissent des fonctionnalités supplémentaires telles que le comptage de références, le transfert de propriété, la gestion de la durée de vie, etc.
En Rust, la bibliothèque standard fournit plusieurs types courants de pointeurs intelligents, tels que Box, Rc, Arc et RefCell.
Cas d'utilisation des pointeurs intelligents :
- Lorsque vous devez allouer de la mémoire sur le tas, utilisez
Box<T>。 - Lorsque plusieurs endroits doivent partager la propriété, utilisez
Rc<T>ouArc<T>。 - Lorsque vous avez besoin de mutabilité intérieure, utilisez
RefCell<T>。 - Lorsque vous avez besoin d'une propriété partagée sûre pour les threads, utilisez
Arc<T>。 - Lorsque vous avez besoin d'un accès mutuellement exclusif aux données, utilisez
Mutex<T>。 - Lorsque vous avez besoin d'un accès en lecture-écriture aux données, utilisez
RwLock<T>。 - Lorsque vous devez résoudre des cycles de référence, utilisez
Weak<T>。
Pointeur intelligent Box<T>
Box<T> est l'un des pointeurs intelligents les plus simples de Rust. Il permet d'allouer un bloc de mémoire sur le tas et d'y stocker une valeur.
En raison des règles de propriété de Rust, l'utilisation de Box permet de créer des données de taille connue sur le tas.
Exemple
println!("b = {}", b);
Pointeur intelligent Rc<T>
Rc<T> (pointeur à comptage de références) permet à plusieurs propriétaires de partager des données. Il utilise le comptage de références pour suivre le nombre de propriétaires des données et libère les données lorsque le nombre de propriétaires atteint zéro.
Rc<T> convient au partage de données dans des environnements monothread.
Exemple
let data = Rc::new(5);
let data_clone = Rc::clone(&data);
Pointeur intelligent Arc<T>
Arc<T> (pointeur à comptage de références atomique) est similaire à Rc<T>, mais il peut partager des données en toute sécurité dans des environnements multi-threadés car il utilise des opérations atomiques pour mettre à jour le compteur de références.
Exemple
let data = Arc::new(5);
let data_clone = Arc::clone(&data);
RefCell<T> Pointeur intelligent
RefCell<T> permet que les règles d'emprunt soient vérifiées à l'exécution. Il utilise la mutabilité intérieure pour fournir un modèle sûr de mutabilité intérieure, permettant de modifier des données en présence de références immuables.
Cependant, RefCell<T> ne peut être utilisé que dans des environnements mono-thread.
Exemple
let data = RefCell::new(5);
let mut borrowed_data = data.borrow_mut();
*borrowed_data = 10;
Mutex<T> Pointeur intelligent
Mutex<T> est un verrou d'exclusion mutuelle qui garantit qu'un seul thread peut accéder aux données à l'intérieur du Mutex à un instant donné.
Exemple
let m = Mutex::new(5);
let mut data = m.lock().unwrap();
RwLock<T> pointeur intelligent
RwLock<T> est un verrou lecture-écriture qui permet à plusieurs lecteurs d'accéder simultanément aux données, mais les écritures sont exclusives.
Exemple
let lock = RwLock::new(5);
let read_guard = lock.read().unwrap();
Weak<T> pointeur intelligent
Weak<T> est un pointeur intelligent non propriétaire de Rc<T>. Il n'augmente pas le compteur de références et est utilisé pour résoudre les problèmes de cycles de références.
Exemple
let five = Rc::new(5);
let weak_five = Rc::downgrade(&five);
Gestion de la durée de vie des pointeurs intelligents
Les pointeurs intelligents peuvent aider à gérer la durée de vie des données. Lorsque les pointeurs intelligents sont détruits, ils libèrent automatiquement la mémoire, évitant ainsi les fuites de mémoire et les pointeurs pendants.
De plus, les pointeurs intelligents permettent de spécifier un destructeur personnalisé au moment de la création afin de réaliser une gestion personnalisée des ressources.
Exemple
Voici un exemple complet d'un pointeur intelligent Rust simple. Cet exemple utilise le pointeur intelligent Rc<T> pour mettre en œuvre une fonctionnalité simple de comptage de références et démontre le partage de données entre plusieurs propriétaires.
Exemple
use std::rc::Rc;
// Définir une structure pour stocker des données
#[derive(Debug)]
struct Data {
value: i32,
}
// Fonction principale
fn main() {
// Créer un pointeur intelligent Rc pour partager des données
let data = Rc::new(Data { value: 5 });
// Cloner le pointeur intelligent Rc pour augmenter le compteur de références de la donnée
let data_clone1 = Rc::clone(&data);
let data_clone2 = Rc::clone(&data);
// Afficher la valeur et le nombre de références de la donnée
println!("Valeur des données : {}", data.value);
println!("Nombre de références : {}", Rc::strong_count(&data));
// Afficher le pointeur intelligent Rc cloné
println!("Clone de données 1 : {:?}", data_clone1);
println!("Clone de données 2 : {:?}", data_clone2);
}
Dans le code ci-dessus, nous définissons d'abord uneDatastruct pour stocker une valeur entière. Ensuite, dans lamainfonction, nous avons créé unRc<Data>pointeur intelligent pour partager des données. Ensuite, en utilisant laRc::cloneméthode, nous avons cloné deux pointeurs intelligents, augmentant le nombre de références de la donnée. Enfin, nous avons affiché la valeur de la donnée, le nombre de références et les pointeurs intelligents clonés.
Lors de l'exécution du programme, vous pouvez voir qu'il affiche la valeur et le compteur de références de la donnée, ainsi que les pointeurs intelligents clonés. CommeRcles pointeurs intelligents utilisent le comptage de références pour suivre le nombre de propriétaires de la donnée, donc chaque fois qu'il est cloné, le compteur de références de la donnée augmente, et lorsque le nombre de propriétaires atteint zéro, la donnée est automatiquement libérée.
La sortie est la suivante :
Data value: 5
Reference count: 3
Data clone 1: Data { value: 5 }
Data clone 2: Data { value: 5 }Résumé
Les pointeurs intelligents de Rust offrent un moyen sûr et automatique de gérer la mémoire et la propriété partagée.
Les pointeurs intelligents sont une structure de données très importante en Rust. Ils offrent un moyen sûr, flexible et pratique de gérer la mémoire, aident les programmeurs à éviter les problèmes courants de sûreté mémoire et améliorent la fiabilité et la maintenabilité du code.
Les pointeurs intelligents sont une partie importante du modèle de sûreté de Rust, permettant aux développeurs d'écrire du code de bas niveau sans se soucier de la sûreté mémoire.
Grâce aux pointeurs intelligents, Rust conserve le contrôle du C tout en évitant ses risques.
Autres extensions