Ruggine - Proprietà

La memoria per un programma può essere allocata come segue:

  • Stack
  • Heap

Pila

Una pila segue l'ultima in ordine di prima uscita. Stack memorizza i valori dei dati per i quali la dimensione è nota in fase di compilazione. Ad esempio, una variabile di dimensione fissa i32 è una candidata per l'allocazione dello stack. La sua dimensione è nota in fase di compilazione. Tutti i tipi scalari possono essere memorizzati nello stack poiché la dimensione è fissa.

Considera un esempio di stringa, a cui viene assegnato un valore in fase di esecuzione. La dimensione esatta di una stringa di questo tipo non può essere determinata in fase di compilazione. Quindi non è un candidato per l'allocazione dello stack ma per l'allocazione dell'heap.

Mucchio

La memoria heap memorizza i valori dei dati la cui dimensione è sconosciuta al momento della compilazione. Viene utilizzato per memorizzare dati dinamici. In poche parole, una memoria heap viene allocata ai valori dei dati che possono cambiare durante il ciclo di vita del programma. L'heap è un'area della memoria meno organizzata rispetto allo stack.

Cos'è la proprietà?

Ogni valore in Rust ha una variabile che viene chiamata ownerdel valore. Ogni dato archiviato in Rust avrà un proprietario ad esso associato. Ad esempio, nella sintassi - let age = 30, age è il proprietario del valore 30 .

  • Ogni dato può avere un solo proprietario alla volta.

  • Due variabili non possono puntare alla stessa posizione di memoria. Le variabili punteranno sempre a diverse posizioni di memoria.

Trasferimento della proprietà

La proprietà del valore può essere trasferita da:

  • Assegnazione del valore di una variabile a un'altra variabile.

  • Passaggio di valore a una funzione.

  • Restituzione di valore da una funzione.

Assegnazione del valore di una variabile a un'altra variabile

Il punto chiave di vendita di Rust come linguaggio è la sua sicurezza nella memoria. La sicurezza della memoria si ottiene controllando strettamente chi può usare cosa e quando le restrizioni.

Considera il seguente frammento:

fn main(){
   let v = vec![1,2,3]; 
   // vector v owns the object in heap

   //only a single variable owns the heap memory at any given time
   let v2 = v; 
   // here two variables owns heap value,
   //two pointers to the same content is not allowed in rust

   //Rust is very smart in terms of memory access ,so it detects a race condition
   //as two variables point to same heap

   println!("{:?}",v);
}

L'esempio precedente dichiara un vettore v. L'idea di proprietà è che solo una variabile si lega a una risorsa v si lega alla risorsa o v2si lega alla risorsa. L'esempio precedente genera un errore: l' uso del valore spostato: `v` . Questo perché la proprietà della risorsa viene trasferita alla v2. Significa che la proprietà viene spostata da v2 (v2 = v) e v viene invalidata dopo lo spostamento.

Passaggio di valore a una funzione

La proprietà di un valore cambia anche quando passiamo un oggetto nell'heap a una chiusura o funzione.

fn main(){
   let v = vec![1,2,3];     // vector v owns the object in heap
   let v2 = v;              // moves ownership to v2
   display(v2);             // v2 is moved to display and v2 is invalidated
   println!("In main {:?}",v2);    //v2 is No longer usable here
}
fn display(v:Vec<i32>){
   println!("inside display {:?}",v);
}

Restituzione di valore da una funzione

La proprietà passata alla funzione verrà invalidata al termine dell'esecuzione della funzione. Un modo per aggirare questo problema è lasciare che la funzione restituisca l'oggetto di proprietà al chiamante.

fn main(){
   let v = vec![1,2,3];       // vector v owns the object in heap
   let v2 = v;                // moves ownership to v2
   let v2_return = display(v2);    
   println!("In main {:?}",v2_return);
}
fn display(v:Vec<i32>)->Vec<i32> { 
   // returning same vector
   println!("inside display {:?}",v);
}

Proprietà e tipi primitivi

In caso di tipi primitivi, il contenuto di una variabile viene copiato in un'altra. Quindi, non si verifica alcun trasferimento di proprietà. Questo perché una variabile primitiva richiede meno risorse di un oggetto. Considera il seguente esempio:

fn main(){
   let u1 = 10;
   let u2 = u1;  // u1 value copied(not moved) to u2

   println!("u1 = {}",u1);
}

L'output sarà - 10.