Tranches de Vec<T> en Rust : comment ça fonctionne et pourquoi en avez-vous besoin ?
\n\nSi vous avez déjà écrit en Rust et vous êtes demandé "How do I get a slice of a Vec<T> in Rust?" — vous n'êtes pas seul. C'est l'une des questions les plus populaires sur Stack Overflow, avec des milliers de vues. Et pour cause : travailler avec des vecteurs et leurs tranches est une compétence fondamentale, sans laquelle aucun projet sérieux en Rust ne peut être imaginé.
\n\nDans cet article, nous ne montrerons pas seulement comment obtenir une tranche. Nous analyserons les meilleures pratiques de 2025, apprendrons à éviter les pièges typiques et comprendrons pourquoi Rust nous oblige à tant réfléchir aux emprunts. C'est parti !
\n\nQu'est-ce qu'une tranche (slice) en Rust ?
\n\nAvant de prendre une tranche, comprenons ce que c'est. Une tranche est une référence à une séquence continue d'éléments en mémoire. En Rust, une tranche est notée &[T]. Ce n'est pas une structure de données propriétaire — elle se contente de « regarder » une partie des données appartenant à quelqu'un d'autre (par exemple, un vecteur ou un tableau).
Le principal avantage des tranches est la sécurité. Le compilateur Rust garantit que vous ne sortirez pas des limites de la mémoire, et le système d'emprunt ne vous permettra pas de modifier les données tant qu'il y a des références actives dessus.
\n\nPourquoi ne pas utiliser directement le vecteur ?
\n\nUn vecteur (Vec<T>) est une structure propriétaire. Si vous le passez à une fonction, soit vous le déplacez (perdant l'accès), soit vous passez une référence. Les tranches vous offrent de la flexibilité : vous pouvez transmettre seulement une partie des données, sans les copier et sans perdre le contrôle sur le vecteur d'origine.
Par exemple, vous travaillez avec un grand tableau de données et souhaitez passer un fragment à une fonction pour analyse. La tranche est l'outil idéal : elle est légère (seulement deux mots : pointeur et longueur) et sécurisée.
\n\nPrincipales façons d'obtenir une tranche de Vec<T>
\n\nPassons à la pratique. Il existe plusieurs façons d'obtenir une tranche à partir d'un vecteur. Nous examinerons les plus populaires et pratiques.
\n\n1. Opérateur d'indexation : &vec[start..end]
\n\nLa manière la plus directe est d'utiliser l'opérateur de plage .. :
let vec = vec![1, 2, 3, 4, 5];\nlet slice: &[i32] = &vec[1..4]; // tranche de l'index 1 à 4 (non inclus)\nprintln!("{:?}", slice); // [2, 3, 4]\n\nCette méthode utilise une vérification des limites à l'exécution. Si vous dépassez les limites du vecteur, le programme paniquera (panic). Pour des exemples pédagogiques, c'est acceptable, mais dans du code de production, il faut être prudent.
\n\nVous pouvez utiliser différentes formes de plages :
\n\n- \n
&vec[..]— tout le vecteur \n&vec[2..]— de l'index 2 à la fin \n&vec[..3]— du début à l'index 3 (non inclus) \n&vec[1..=3]— de 1 à 3 inclus \n
2. Méthode .as_slice()
\n\nCette méthode retourne une tranche sur tout le vecteur. Elle est plus sûre que &vec[..] car elle exprime clairement l'intention :
let vec = vec![10, 20, 30];\nlet slice: &[i32] = vec.as_slice();\nprintln!("{:?}", slice); // [10, 20, 30]\n\nLa méthode as_slice() est particulièrement utile lorsque vous voulez souligner que vous travaillez avec une tranche, et non avec un vecteur. Cela rend le code plus lisible et auto-documenté.
3. Obtenir une tranche mutable : as_mut_slice()
\n\nSi vous devez modifier les éléments à l'intérieur de la tranche (mais pas le vecteur lui-même), utilisez as_mut_slice() :
let mut vec = vec![1, 2, 3];\nlet slice: &mut [i32] = vec.as_mut_slice();\nslice[0] = 100;\nprintln!("{:?}", vec); // [100, 2, 3]\n\nNotez que le vecteur doit être déclaré comme mut. Vous ne pouvez pas non plus avoir simultanément des tranches immuables et mutables — cela violerait les règles d'emprunt.