Ricerca…


introduzione

La proprietà è uno dei concetti più importanti in Rust, ed è qualcosa che non è presente nella maggior parte delle altre lingue. L'idea che un valore possa appartenere a una determinata variabile è spesso abbastanza difficile da comprendere, specialmente nelle lingue in cui la copia è implicita, ma questa sezione esaminerà le diverse idee relative alla proprietà.

Sintassi

  • let x: & T = ... // x è un riferimento immutabile
  • sia x: & mut T = ... // x è un riferimento esclusivo e mutevole
  • lasciamo _ = & mut foo; // prendere in prestito in modo mutabile (cioè, esclusivamente)
  • lasciamo _ = & foo; // prendo in prestito immutabilmente
  • lascia _ = pippo; // move foo (richiede la proprietà)

Osservazioni

  • Nelle versioni molto vecchie di Rust (prima di 1.0, maggio 2015), una variabile di proprietà aveva un tipo che inizia con ~ . Si può vedere questo in esempi molto vecchi.

Proprietà e prestito

Tutti i valori in Rust hanno esattamente un proprietario. Il proprietario è responsabile di rilasciare quel valore quando esce dal campo di applicazione ed è l'unico che può spostare la proprietà del valore. Il proprietario di un valore può dare dei riferimenti ad esso lasciando che altri pezzi di codice prendano in prestito quel valore. In qualsiasi momento, potrebbe esserci un numero qualsiasi di riferimenti immutabili a un valore:

let owned = String::from("hello");
// since we own the value, we may let other variables borrow it
let immutable_borrow1 = &owned;
// as all current borrows are immutable, we can allow many of them
let immutable_borrow2 = &owned;
// in fact, if we have an immutable reference, we are also free to
// duplicate that reference, since we maintain the invariant that
// there are only immutable references
let immutable_borrow3 = &*immutable_borrow2;

o un singolo riferimento mutabile ( ERROR denota un errore in fase di compilazione):

// for us to borrow a value mutably, it must be mutable
let mut owned = String::from("hello");
// we can borrow owned mutably
let mutable_borrow = &mut owned;
// but note that we cannot borrow owned *again*
let mutable_borrow2 = &mut owned; // ERROR, already borrowed
// nor can we cannot borrow owned immutably
// since a mutable borrow is exclusive.
let immutable_borrow = &owned; // ERROR, already borrowed

Se ci sono riferimenti in sospeso (mutabili o immutabili) a un valore, tale valore non può essere spostato (cioè, la sua proprietà è data via). Dovremmo assicurarci che prima tutti i riferimenti siano stati rilasciati per poter spostare un valore:

let foo = owned; // ERROR, outstanding references to owned
let owned = String::from("hello");
{
    let borrow = &owned;
    // ...
} // the scope ends the borrow
let foo = owned; // OK, owned and not borrowed

Prende in prestito e vite

Tutti i valori in Rust hanno una durata . La durata di un valore copre il segmento di codice dal valore introdotto al punto in cui viene spostato o alla fine dell'ambito di contenimento

{
    let x = String::from("hello"); //             +
    // ...                                        :
    let y = String::from("hello"); //      +      |
    // ...                                 :      :
    foo(x) // x is moved                   |      = x's lifetime
    // ...                                 :
} //                                       = y's lifetime

Ogni volta che si prende in prestito un valore, il riferimento risultante ha una durata legata alla durata del valore preso in prestito:

{
    let x = String::from("hello");
    let y = String::from("world");
    // when we borrow y here, the lifetime of the reference
    // stored in foo is equal to the lifetime of y
    // (i.e., between let y = above, to the end of the scope below)
    let foo = &y;
    // similarly, this reference to x is bound to the lifetime
    // of x --- bar cannot, for example, spawn a thread that uses
    // the reference beyond where x is moved below.
    bar(&x);
}

Proprietà e chiamate di funzione

La maggior parte delle domande relative alla proprietà si verificano quando si scrivono le funzioni. Quando si specificano i tipi di argomenti di una funzione, è possibile scegliere in che modo viene passato quel valore. Se è necessario solo l'accesso di sola lettura, è possibile prendere un riferimento immutabile:

fn foo(x: &String) {
    // foo is only authorized to read x's contents, and to create
    // additional immutable references to it if it so desires.
    let y = *x; // ERROR, cannot move when not owned
    x.push_str("foo"); // ERROR, cannot mutate with immutable reference
    println!("{}", x.len()); // reading OK
    foo(x); // forwarding reference OK
}

Se foo bisogno di modificare l'argomento, dovrebbe avere un riferimento esclusivo e mutevole:

fn foo(x: &mut String) {
    // foo is still not responsible for dropping x before returning,
    // nor is it allowed to. however, foo may modify the String.
    let x2 = *x; // ERROR, cannot move when not owned
    x.push_str("foo"); // mutating OK
    drop(*x); // ERROR, cannot drop value when not owned
    println!("{}", x.len()); // reading OK
}

Se non si specifica né & o &mut , si sta dicendo che la funzione assumerà la proprietà di un argomento. Ciò significa che foo è ora anche responsabile della caduta di x .

fn foo(x: String) {
    // foo may do whatever it wishes with x, since no-one else has
    // access to it. once the function terminates, x will be dropped,
    // unless it is moved away when calling another function.
    let mut x2 = x; // moving OK
    x2.push_str("foo"); // mutating OK
    let _ = &mut x2; // mutable borrow OK
    let _ = &x2; // immutable borrow OK (note that &mut above is dropped)
    println!("{}", x2.len()); // reading OK
    drop(x2); // dropping OK
}

Proprietà e il tratto di copia

Alcuni tipi di ruggine implementano il tratto Copy . I tipi che sono Copy possono essere spostati senza possedere il valore in questione. Questo perché il contenuto del valore può essere semplicemente copiato byte per byte in memoria per produrre un nuovo valore identico. La maggior parte dei primitivi in ​​Rust ( bool , usize , f64 , ecc.) Sono Copy .

let x: isize = 42;
let xr = &x;
let y = *xr; // OK, because isize is Copy
// both x and y are owned here

In particolare, Vec e String non sono Copy :

let x = Vec::new();
let xr = &x;
let y = *xr; // ERROR, cannot move out of borrowed content


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow