I just came across the following code in 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} }]
link to rust playground
It's apparently v1
has 2 different HashMaps, while v2
has only one. How's that happened? Shouldn't v2
evaluates Arc::new(Mutex::new(HashMap::<i32, i32>::new()))
twice (like v1
do) and thus create two different elements? Is it some kind of "lazy" evaluation somewhere?
Pardon my rust newbie question, thanks in advance!
The vec![value; n]
syntax uses Clone
to duplicate the value and fill up the vector. The docs even mention this kind of scenario:
This will use
clone
to duplicate an expression, so one should be careful using this with types having a nonstandardClone
implementation. For example,vec![Rc::new(1); 5]
will create a vector of five references to the same boxed integer value, not five references pointing to independently boxed integers.
The vec!
macro clones value of the provided expression to fill the vector up to the requested length.
An Arc
is a reference-counted smart pointer, which is shared by cloning. Each time you clone an Arc
, it increases the reference count to the underlying data, but the underlying data is still the same.
So that's what is happening in your example. The elements of the vector are different pointers to the same HashMap
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With