Rust
Äganderätt
Sök…
Introduktion
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