Quand «vec!» Crée-t-il différents éléments, ou pas?
Je viens de tomber sur le code suivant dans Rust:
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
fn main() {
let mut v1 = vec![HashMap::<i32, i32>::new(); 2];
v1[0].insert(0,0);
v1[1].insert(1,1);
println!("{:?}", v1);
let v2 = vec![Arc::new(Mutex::new(HashMap::<i32, i32>::new())); 2];
v2[0].lock().unwrap().insert(0,0);
v2[1].lock().unwrap().insert(1,1);
println!("{:?}", v2);
}
// outputs:
// [{0: 0}, {1: 1}]
// [Mutex { data: {0: 0, 1: 1} }, Mutex { data: {0: 0, 1: 1} }]
lien vers le terrain de jeu de la rouille
Il a apparemment v12 HashMaps différents, alors qu'il v2n'en a qu'un seul. Comment est-ce arrivé? Ne devrait-il pas v2évaluer Arc::new(Mutex::new(HashMap::<i32, i32>::new()))deux fois (comme le v1font) et créer ainsi deux éléments différents? S'agit-il d'une sorte d'évaluation «paresseuse» quelque part?
Pardonnez ma question de débutant à la rouille, merci d'avance!
Réponses
La vec![value; n]syntaxe utilise Clonepour dupliquer la valeur et remplir le vecteur. La documentation mentionne même ce genre de scénario:
Cela utilisera
clonepour dupliquer une expression, donc il faut être prudent en utilisant cela avec des types ayant uneCloneimplémentation non standard . Par exemple,vec![Rc::new(1); 5]créera un vecteur de cinq références à la même valeur entière encadrée, et non pas cinq références pointant vers des entiers encadrés indépendamment.
La vec!macro clone la valeur de l'expression fournie pour remplir le vecteur jusqu'à la longueur demandée.
An Arcest un pointeur intelligent compté par référence, qui est partagé par clonage. Chaque fois que vous clonez un Arc, cela augmente le nombre de références aux données sous-jacentes, mais les données sous-jacentes sont toujours les mêmes.
C'est donc ce qui se passe dans votre exemple. Les éléments du vecteur sont des pointeurs différents vers le même HashMap.