Recherche…


Introduction

La propriété est l’un des concepts les plus importants de Rust, et elle n’est pas présente dans la plupart des autres langues. L'idée qu'une valeur puisse appartenir à une variable particulière est souvent assez difficile à comprendre, en particulier dans les langues où la copie est implicite, mais cette section passera en revue les différentes idées concernant la propriété.

Syntaxe

  • Soit x: & T = ... // x est une référence immuable
  • Soit x: & mut T = ... // x est une référence exclusive, mutable
  • let _ = & mut foo; // emprunter de façon mutuelle (c’est-à-dire exclusivement)
  • let _ = & foo; // emprunter immanquablement
  • let _ = foo; // déplace foo (nécessite la propriété)

Remarques

  • Dans les versions beaucoup plus anciennes de Rust (avant 1.0; mai 2015), une variable possédée avait un type commençant par ~ . Vous pouvez voir cela dans des exemples très anciens.

Propriété et emprunt

Toutes les valeurs dans Rust ont exactement un propriétaire. Le propriétaire est responsable de la suppression de cette valeur lorsqu'il est hors de portée et est le seul à pouvoir transférer la propriété de la valeur. Le propriétaire d'une valeur peut lui donner des références en laissant d'autres parties de code emprunter cette valeur. À tout moment, il peut y avoir un certain nombre de références immuables à une valeur:

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;

ou une seule référence mutable ( ERROR indique une ERROR compilation):

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

S'il existe des références en attente (mutables ou immuables) à une valeur, cette valeur ne peut pas être déplacée (c.-à-d. Que sa propriété est donnée). Nous devrions nous assurer que toutes les références ont été supprimées en premier pour pouvoir déplacer une valeur:

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

Emprunts et vies

Toutes les valeurs de Rust ont une durée de vie . La durée de vie d'une valeur couvre le segment de code de la valeur introduit à l'endroit où il est déplacé ou la fin de l'étendue contenant

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

Chaque fois que vous empruntez une valeur, la référence résultante a une durée de vie liée à la durée de vie de la valeur empruntée:

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

Appels de propriété et fonction

La plupart des questions relatives à la propriété apparaissent lors de l'écriture de fonctions. Lorsque vous spécifiez les types d'arguments d'une fonction, vous pouvez choisir la manière dont cette valeur est transmise. Si vous avez uniquement besoin d'un accès en lecture seule, vous pouvez prendre une référence immuable:

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
}

Si foo besoin de modifier l'argument, il devrait prendre une référence exclusive, mutable:

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
}

Si vous ne spécifiez ni & ni &mut , vous dites que la fonction prendra possession d'un argument. Cela signifie que foo est maintenant aussi responsable de laisser tomber 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
}

Propriété et copie

Certains types de rouille implémentent le trait de Copy . Les types qui sont Copy peuvent être déplacés sans posséder la valeur en question. En effet, le contenu de la valeur peut simplement être copié octet par octet dans la mémoire pour produire une nouvelle valeur identique. La plupart des primitives de Rust ( bool , usize , f64 , etc.) sont des Copy .

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

Notamment, Vec et String ne sont pas des 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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow