Je joue avec Rust , et j'essaie d'accéder au premier argument de ligne de commande avec ce code:
use std::env;
fn main() {
let args: Vec<_> = env::args().collect();
let dir = args[1];
}
Et je reçois cette erreur:
error[E0507]: cannot move out of indexed content
--> src/main.rs:5:15
|
5 | let dir = args[1];
| --- ^^^^^^^ cannot move out of indexed content
| |
| hint: to prevent move, use `ref dir` or `ref mut dir`
Si je le change en let ref dir
, ça compile, mais je ne vois pas ce qui se passe. Quelqu'un pourrait-il expliquer ce que signifie "contenu indexé"?
Lorsque vous utilisez un opérateur d'index ([]
), Vous obtenez l'objet réel à l'emplacement d'index. Vous n'obtenez pas de référence, de pointeur ou de copie. Puisque vous essayez de lier cet objet avec une liaison let
, Rust essaie immédiatement de se déplacer (ou de copier, si le trait Copy
est implémenté).
Dans votre exemple, env::args()
est un itérateur de String
s qui est ensuite collecté dans un Vec<String>
. Il s'agit d'un vecteur appartenant à des chaînes possédées, et les chaînes possédées ne sont pas automatiquement copiables.
Vous pouvez utiliser une liaison let ref
, Mais l'alternative la plus idiomatique consiste à prendre une référence à l'objet indexé (notez le symbole &
):
use std::env;
fn main() {
let args: Vec<_> = env::args().collect();
let ref dir = &args[1];
// ^
}
Le déplacement implicite d'un Vec
n'est pas autorisé car il le laisserait dans un état invalide - un élément est déplacé, les autres ne le sont pas. Si vous avez un Vec
modifiable, vous pouvez utiliser une méthode comme Vec::remove
pour supprimer une seule valeur:
use std::env;
fn main() {
let mut args: Vec<_> = env::args().collect();
let dir = args.remove(1);
}
Pour votre problème particulier, vous pouvez également utiliser simplement Iterator::nth
:
use std::env;
fn main() {
let dir = env::args().nth(1).expect("Missing argument");
}