Sök…


Introduktion

Äganderätt är ett av de viktigaste begreppen i Rust, och det är något som inte finns på de flesta andra språk. Tanken att ett värde kan ägas av en viss variabel är ofta ganska svår att förstå, särskilt på språk där kopiering är implicit, men det här avsnittet kommer att granska de olika idéerna kring ägandet.

Syntax

  • låt x: & T = ... // x är en oändlig referens
  • låt x: & mut T = ... // x är en exklusiv, muterbar referens
  • låt _ = & mut foo; // låna foo på ett annat sätt (dvs. exklusivt)
  • låt _ = & foo; // låna foo omöjligt
  • låt _ = foo; // flytta foo (kräver ägande)

Anmärkningar

  • I mycket äldre versioner av Rust (före 1.0; maj 2015) hade en ägd variabel en typ som börjar med ~ . Du kan se detta i mycket gamla exempel.

Äganderätt och upplåning

Alla värden i Rust har exakt en ägare. Ägaren är ansvarig för att släppa det värdet när det går utanför räckvidden och är den enda som kan flytta ägandet av värdet. Ägaren till ett värde kan ge bort referenser till det genom att låta andra kodkodlån låna det värdet. Vid varje given tidpunkt kan det finnas ett antal immutable referenser till ett värde:

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;

eller en enda muterbar referens till den ( ERROR anger ett kompileringstidsfel):

// 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

Om det finns utestående referenser (antingen muterbara eller immutable) till ett värde, kan det värdet inte flyttas (det vill säga att dess ägande givits bort). Vi måste se till att alla referenser tappades först för att få flytta ett värde:

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

Lånar och livstid

Alla värden i Rust har en livstid . En värdes livslängd sträcker sig över kodsegmentet från värdet införs dit det flyttas, eller slutet på det innehållande omfånget

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

När du lånar ett värde har den resulterande referensen en livstid som är bunden till livslängden på det värde som lånas:

{
    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);
}

Ägar- och funktionssamtal

De flesta frågorna kring äganderätt dyker upp när man skriver funktioner. När du anger typerna för en funktionsargument kan du välja hur det värdet ska skickas in. Om du bara behöver skrivskyddad åtkomst kan du ta en immutabel referens:

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
}

Om foo behöver ändra argumentet, bör det ta en exklusiv, muterbar referens:

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
}

Om du inte anger antingen & eller &mut säger du att funktionen kommer att äga ett argument. Detta innebär att foo nu också ansvarar för att släppa 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
}

Äganderätt och kopieringsegenskapen

Vissa rosttyper implementerar Copy . Typer som är Copy kan flyttas utan att äga det aktuella värdet. Detta beror på att innehållet i värdet helt enkelt kan kopieras byte-för-byte i minnet för att producera ett nytt, identiskt värde. De flesta primitiven i Rust ( bool , usize , f64 , etc.) är Copy .

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

Noterbart är Vec och String inte 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow