¿Cuándo crea `vec!` Diferentes elementos, o no?

Oct 21 2020

Me encontré con el siguiente código en 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} }]

enlace al patio de recreo de óxido

Aparentemente v1tiene 2 HashMaps diferentes, mientras que v2solo tiene uno. ¿Cómo fue eso? ¿No debería v2evaluar Arc::new(Mutex::new(HashMap::<i32, i32>::new()))dos veces (como v1hacer) y así crear dos elementos diferentes? ¿Es una especie de evaluación "perezosa" en alguna parte?

Disculpe mi pregunta de novato de óxido, ¡gracias de antemano!

Respuestas

9 kmdreko Oct 21 2020 at 14:06

La vec![value; n]sintaxis se utiliza Clonepara duplicar el valor y completar el vector. Los documentos incluso mencionan este tipo de escenario:

Esto se usará clonepara duplicar una expresión, por lo que se debe tener cuidado al usar esto con tipos que tienen una Cloneimplementación no estándar . Por ejemplo, vec![Rc::new(1); 5]creará un vector de cinco referencias al mismo valor entero en caja, no cinco referencias que apunten a números enteros en caja de forma independiente.

3 PeterHall Oct 21 2020 at 14:03

La vec!macro clona el valor de la expresión proporcionada para llenar el vector hasta la longitud solicitada.

An Arces un puntero inteligente contado por referencias, que se comparte mediante la clonación. Cada vez que clona un Arc, aumenta el recuento de referencias a los datos subyacentes, pero los datos subyacentes siguen siendo los mismos.

Entonces eso es lo que está sucediendo en tu ejemplo. Los elementos del vector son punteros diferentes al mismo HashMap.