Quando "vec!" Crea elementi differenti o no?

Oct 21 2020

Ho appena trovato il seguente codice 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} }]

collegamento al parco giochi ruggine

Apparentemente v1ha 2 diverse HashMap, mentre ne v2ha solo una. Come è successo? Non dovrebbe v2valutare Arc::new(Mutex::new(HashMap::<i32, i32>::new()))due volte (come v1fare) e quindi creare due elementi diversi? È una sorta di valutazione "pigra" da qualche parte?

Perdonate la mia domanda da principiante ruggine, grazie in anticipo!

Risposte

9 kmdreko Oct 21 2020 at 14:06

La vec![value; n]sintassi utilizza Cloneper duplicare il valore e riempire il vettore. I documenti menzionano anche questo tipo di scenario:

Questo userà cloneper duplicare un'espressione, quindi dovresti stare attento a usarlo con tipi che hanno Cloneun'implementazione non standard . Ad esempio, vec![Rc::new(1); 5]creerà un vettore di cinque riferimenti allo stesso valore intero boxed, non cinque riferimenti che puntano a interi boxed indipendentemente.

3 PeterHall Oct 21 2020 at 14:03

La vec!macro clona il valore dell'espressione fornita per riempire il vettore fino alla lunghezza richiesta.

An Arcè un puntatore intelligente con conteggio dei riferimenti, condiviso dalla clonazione. Ogni volta che si clona un Arc, aumenta il conteggio dei riferimenti ai dati sottostanti, ma i dati sottostanti sono sempre gli stessi.

Quindi questo è ciò che sta accadendo nel tuo esempio. Gli elementi del vettore sono diversi puntatori allo stesso HashMap.