Les Vecteurs en Rust : des listes modifiables
Dans cet article, on va plonger dans un type de collection essentiel en Rust : les vecteurs. Si tu as déjà travaillé avec des tableaux dynamiques dans d’autres langages (comme les listes en Python ou les tableaux redimensionnables en C++), alors les vecteurs te seront familiers. En Rust, les vecteurs sont extrêmement utiles pour stocker et manipuler des ensembles de données de taille dynamique, tout en garantissant la sécurité mémoire.
Qu’est-ce qu’un Vecteur ?
Un vecteur en Rust est une collection qui peut stocker plusieurs valeurs dans un ordre séquentiel. Contrairement aux tableaux (array), dont la taille est fixe, un vecteur peut croître ou diminuer dynamiquement en fonction des besoins. Les éléments d’un vecteur doivent être du même type.
En Rust, les vecteurs sont représentés par la structure Vec
Voici un exemple basique de création d’un vecteur :
Dans cet exemple, on crée un vecteur vide avec Vec::new() et on ajoute des éléments avec la méthode push().
Différentes façons de créer un vecteur
Rust offre plusieurs moyens de créer des vecteurs. Voici quelques exemples :
1. Utiliser Vec::new()
C’est la méthode la plus basique pour créer un vecteur vide :
2. Utiliser la macro vec![]
L’approche la plus simple et la plus courante est d’utiliser la macro vec![], qui permet de créer un vecteur avec des éléments initiaux :
3. Avec une capacité prédéfinie
Si tu connais à l’avance la taille que prendra ton vecteur, tu peux l’initialiser avec une capacité définie. Cela évite des réallocations coûteuses si le vecteur grandit souvent :
Manipuler les éléments d’un vecteur
Les vecteurs en Rust permettent une grande flexibilité pour ajouter, accéder et modifier les éléments.
1. Ajouter des éléments
Comme vu précédemment, la méthode push() permet d’ajouter un élément à la fin d’un vecteur :
2. Accéder aux éléments
Pour accéder aux éléments d’un vecteur, tu peux utiliser l’indexation, mais il y a deux façons de le faire en Rust :
Utiliser la méthode get(), qui retourne une option (Option<&T>) afin de prévenir les accès hors limites :
3. Modifier des éléments
Pour modifier un élément, il faut une référence mutable :
4. Supprimer des éléments
Pour supprimer des éléments, tu peux utiliser pop() pour retirer le dernier élément du vecteur :
pop() retourne un Option
Propriété et emprunts dans les vecteurs
Rust impose des règles strictes sur la gestion des références, même pour les vecteurs. Lorsque tu empruntes une référence mutable à un vecteur (&mut), tu ne peux pas emprunter une référence partagée (&) au même vecteur en même temps.
Prenons un exemple simple :
Pour éviter ces erreurs, assure-toi que les emprunts mutables et partagés ne se chevauchent pas.
Parcourir un vecteur
Tu peux parcourir un vecteur de plusieurs façons en Rust :
1. Avec une boucle for
La façon la plus simple est d’utiliser une boucle for pour parcourir chaque élément :
2. Itérateurs
Rust propose aussi un système d’itérateurs très puissant. Tu peux obtenir un itérateur avec la méthode iter() :
Pour modifier les éléments d’un vecteur pendant l’itération, utilise iter_mut() :
Les vecteurs et la gestion mémoire
Rust gère la mémoire des vecteurs de manière très efficace grâce à son système de pile et tas. Quand tu crées un vecteur, les métadonnées (comme la taille, la capacité et un pointeur vers les éléments) sont stockées sur la pile, mais les éléments eux-mêmes sont stockés sur le tas.
Chaque fois que tu ajoutes des éléments au vecteur, Rust peut réallouer de l’espace sur le tas si la capacité est dépassée. C’est pour cela qu’il est souvent utile de pré-allouer de la capacité si tu sais à l’avance combien d’éléments tu vas stocker. Performances des vecteurs
En termes de performances, les vecteurs offrent un accès en temps constant (O(1)) à un élément via son index. Cependant, certaines opérations, comme l’insertion ou la suppression d’éléments, peuvent être plus coûteuses si elles nécessitent de déplacer plusieurs éléments.
Si tu ajoutes souvent des éléments à la fin du vecteur, l’opération reste efficace. En revanche, insérer ou supprimer des éléments au milieu du vecteur peut être plus coûteux, car cela entraîne des décalages d’éléments.
Conclusion
Les vecteurs sont une structure de données flexible et puissante en Rust, permettant de stocker des données dynamiques avec un contrôle total sur la gestion mémoire. En comprenant comment les utiliser efficacement et en respectant les règles de propriété et d’emprunt, tu pourras tirer le meilleur parti des vecteurs dans tes projets.
Que ce soit pour des collections simples ou pour des structures de données plus complexes, les vecteurs sont un outil essentiel à maîtriser pour écrire des programmes performants et sûrs en Rust. N’hésite pas à expérimenter avec les vecteurs et à découvrir leur flexibilité !