0Pricing
Learn Rust Coding · Lezione

Smart pointer Box, Rc e Arc

Comprenda come `Box` per l’allocazione nell’heap, `Rc` per l’ownership condivisa e `Arc` per l’ownership condivisa sicura tra thread gestiscono i dati.

Smart pointer Box, Rc e Arc è una lezione Learn Rust Coding gratuita su CoddyKit. Questa è la lezione 1 di 3. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Learn Rust Coding, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Learn Rust Coding include 3 lezioni in totale.

Cosa sono gli smart pointer?

Il sistema di ownership di Rust è ottimo per la sicurezza della memoria, ma a volte serve maggiore flessibilità. È qui che entrano in gioco gli smart pointer!

Gli smart pointer sono strutture dati che si comportano come puntatori, ma includono anche metadati e funzionalità aggiuntive. Gestiscono automaticamente memoria, ownership e altre risorse.

Box: memorizzare dati nell'heap

Lo smart pointer più semplice è Box<T>. Consente di memorizzare i dati nell'heap invece che nello stack.

  • Stack: dati veloci e di dimensione fissa.
  • Heap: dati più lenti e di dimensione flessibile, allocati a runtime.

Quando si inserisce un valore in un Box, il Box si trova nello stack, mentre i dati a cui punta risiedono nell'heap.

Usare Box per l'allocazione nell'heap

Vediamo come Box sposta i dati nell'heap. È utile per dati di grandi dimensioni o quando non se ne conosce la dimensione al momento della compilazione.

Eseguite questo codice per osservare come un valore viene inserito in un Box.

fn main() {
  let x = 5; // x is on the stack
  let boxed_x = Box::new(x); // x's value is moved to the heap, boxed_x is on stack
  println!("Value on stack: {}", x);
  println!("Value in Box (on heap): {}", *boxed_x); // Dereference to get value
}

Quando è utile Box

È possibile usare Box<T> nelle seguenti situazioni:

  • Quando si ha un tipo la cui dimensione non può essere conosciuta al momento della compilazione e lo si deve memorizzare in uno spazio di dimensione nota e fissa.
  • Quando si ha una grande quantità di dati e si vuole trasferirne l'ownership senza copiare i dati stessi.
  • Quando si vuole possedere un trait object, ad esempio Box<dyn Trait>.

Rc: più proprietari (un singolo thread)

Le regole di ownership di Rust fanno sì che un valore abbia generalmente un solo proprietario. Ma cosa succede se più parti del programma devono "possedere" gli stessi dati?

Rc<T>, ovvero Reference Counted, consente a più proprietari di condividere i dati in uno scenario single-threaded. Tiene traccia del numero di riferimenti ai dati.

Quando il conteggio scende a zero, i dati vengono liberati.

Condividere dati con Rc

Rc::clone() incrementa il conteggio dei riferimenti. Non esegue una copia profonda: crea semplicemente un altro puntatore agli stessi dati.

Notate come i dati vengano condivisi e il loro valore sia accessibile da diversi "proprietari".

use std::rc::Rc;

fn main() {
  let value = Rc::new(String::from("Shared String"));
  println!("Count after creation: {}", Rc::strong_count(&value));

  let value_clone_a = Rc::clone(&value); // Increment count
  println!("Count after clone A: {}", Rc::strong_count(&value));

  {
    let value_clone_b = Rc::clone(&value); // Increment count
    println!("Count after clone B: {}", Rc::strong_count(&value));
    println!("Data from A: {}", value_clone_a);
    println!("Data from B: {}", value_clone_b);
  } // value_clone_b goes out of scope, count decreases

  println!("Count after B goes out of scope: {}", Rc::strong_count(&value));
}

Arc: ownership condivisa (più thread)

Rc<T> funziona bene nelle applicazioni single-threaded. Tuttavia, se è necessario condividere dati tra più thread, Rc<T> non è sicuro.

Arc<T>, ovvero Atomic Reference Counted, è la versione thread-safe di Rc<T>. Usa operazioni atomiche per aggiornare il conteggio dei riferimenti, garantendo la sicurezza tra i thread.

Arc ha un lieve sovraccarico in termini di prestazioni rispetto a Rc, dovuto alle operazioni atomiche.

Condividere dati tra thread con Arc

Questo esempio mostra come Arc consenta a più thread di accedere e leggere in sicurezza gli stessi dati condivisi. Ogni thread riceve il proprio clone di `Arc`.

Il thread principale attende il completamento di tutti i thread avviati.

use std::sync::Arc;
use std::thread;

fn main() {
  let data = Arc::new(vec![1, 2, 3, 4, 5]);
  let mut handles = vec![];

  for i in 0..3 {
    let data_clone = Arc::clone(&data); // Clone Arc for each thread
    let handle = thread::spawn(move || {
      println!("Thread {} has data: {:?}", i, *data_clone);
    });
    handles.push(handle);
  }

  for handle in handles {
    handle.join().unwrap();
  }
  println!("All threads finished.");
}

Box, Rc o Arc?

La scelta dello smart pointer corretto dipende dalle vostre esigenze:

  • Box<T>: quando è necessario inserire i dati nell'heap, in genere per la proprietà singola o quando si lavora con tipi ricorsivi.
  • Rc<T>: quando servono più proprietari dei dati in un contesto single-threaded.
  • Arc<T>: quando servono più proprietari dei dati in un contesto multi-threaded (concorrenziale).

Preferite sempre Box o Rc se non vi serve la sicurezza tra thread, poiché Arc comporta un costo in termini di prestazioni.

Verifica sugli smart pointer

Dovete memorizzare un file immagine di grandi dimensioni nell'heap e solo una parte del programma ne avrà la proprietà e la gestione. Quale smart pointer dovreste usare?

Riepilogo: smart pointer

In questa lezione avete imparato a conoscere tre smart pointer fondamentali di Rust:

  • Box<T>: per allocare dati nell'heap con un unico proprietario.
  • Rc<T>: per consentire a più proprietari di condividere dati in un ambiente single-threaded.
  • Arc<T>: per consentire a più proprietari thread-safe di condividere dati in un ambiente multi-threaded.

Questi smart pointer offrono un maggiore controllo sulla gestione della memoria, continuando a sfruttare le garanzie di sicurezza di Rust.

Domande Frequenti

La lezione «Smart pointer Box, Rc e Arc» è gratuita?

Sì — il testo completo di «Smart pointer Box, Rc e Arc» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Learn Rust Coding, passa a CoddyKit PRO. Il corso Learn Rust Coding include 3 lezioni in totale.

Cosa imparerò in «Smart pointer Box, Rc e Arc»?

Comprenda come `Box` per l’allocazione nell’heap, `Rc` per l’ownership condivisa e `Arc` per l’ownership condivisa sicura tra thread gestiscono i dati. Eserciti Learn Rust Coding con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Learn Rust Coding?

Non è richiesta alcuna esperienza precedente. Learn Rust Coding su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 3.

Quanto tempo richiede la lezione «Smart pointer Box, Rc e Arc»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Learn Rust Coding?

Sì. Ogni lezione Learn Rust Coding include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Smart pointer Box, Rc e Arc
  2. Mutabilità interna: RefCell e Cell
  3. Concorrenza senza timori con i thread
← Torna a Learn Rust Coding