Table des matières
Qu'est-ce que Vec::drain() ?
drain() supprime une plage d'éléments d'un Vec tout en cédant leur ownership via un itérateur. Contrairement à truncate() ou clear(), il te permet de traiter les éléments supprimés avant qu'ils ne soient libérés.
Signature
pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
where
R: RangeBounds<usize>,
Caractéristiques principales
| Méthode | Supprime les éléments | Cède l'ownership | Préserve la capacité | Complexité temporelle |
|---|---|---|---|---|
drain(..) |
Oui | ✅ Oui (via itérateur) | ✅ Oui | O(n) |
truncate() |
Oui (à partir d'un index) | ❌ Non | ✅ Oui | O(1) |
clear() |
Tous | ❌ Non | ✅ Oui | O(1) |
Quand utiliser chaque méthode
1. Vec::drain()
Cas d'usage : Traiter les éléments supprimés (par exemple, filtrer, transformer ou supprimer par lots).
Exemple :
let mut vec = vec!['a', 'b', 'c', 'd'];
for ch in vec.drain(1..3) { // Supprime 'b' et 'c'
println!("Supprimé : {}", ch); // Affiche 'b', puis 'c'
}
assert_eq!(vec, ['a', 'd']); // Garde les éléments restants
Performance : Évite les allocations supplémentaires si on réutilise l'itérateur.
2. Vec::truncate()
Cas d'usage : Supprimer rapidement des éléments depuis la fin sans les traiter.
Exemple :
let mut vec = vec![1, 2, 3, 4];
vec.truncate(2); // Libère 3 et 4 (pas d'itérateur)
assert_eq!(vec, [1, 2]);
3. Vec::clear()
Cas d'usage : Supprimer tous les éléments (plus rapide que drain(..) si tu n'en as pas besoin).
Exemple :
let mut vec = vec![1, 2, 3];
vec.clear(); // Libère tous les éléments
assert!(vec.is_empty());
Comportement mémoire
- Les trois méthodes conservent la capacité du Vec (pas de réallocation si des éléments sont rajoutés).
drain()est paresseux : les éléments ne sont libérés que lorsque l'itérateur est consommé.
Cette paresse signifie que le travail intéressant s'étale sur la durée de vie de la garde Drain, et non dans l'appel à drain() :
Utilisation avancée : Réutiliser le stockage
drain() est idéal pour remplacer efficacement un sous-ensemble d'éléments :
let mut vec = vec!["old", "old", "new", "old"];
vec.drain(0..2).for_each(drop); // Supprime les deux premiers
vec.insert(0, "fresh");
assert_eq!(vec, ["fresh", "new", "old"]);
Lequel choisir
- drain() : À utiliser quand tu dois traiter les éléments supprimés ou supprimer par lots.
- truncate()/clear() : À utiliser pour une suppression en masse rapide sans traitement.
- Tous préservent la capacité : Pas de surcoût de réallocation pour les opérations futures.
Exemple concret
Dans un moteur de jeu, drain() pourrait efficacement supprimer les entités expirées tout en permettant une logique de nettoyage (par exemple, sauvegarder l'état).
Un détail qui surprend : libérer un Drain sans le consommer supprime quand même les éléments.
La suppression vit dans le Drop de Drain, pas dans l'itération.