Ricerca…


Sintassi

  • Funzione fn <'a> (x: &' a Type)
  • struct Struct <'a> {x: &' a Type}
  • enum Enum <'a> {Variant (&' a Type)}
  • impl <'a> Struct <' a> {fn x <'a> (& self) -> &' a Type {self.x}}
  • impl <'a> Tratto <' a> per Tipo
  • impl <'a> Tratto per Tipo <' a>
  • fn function<F>(f: F) where for<'a> F: FnOnce(&'a Type)
  • struct Struct<F> where for<'a> F: FnOnce(&'a Type) { x: F }
  • enum Enum<F> where for<'a> F: FnOnce(&'a Type) { Variant(F) }
  • impl<F> Struct<F> where for<'a> F: FnOnce(&'a Type) { fn x(&self) -> &F { &self.x } }

Osservazioni

  • Tutti i riferimenti in Rust hanno una durata, anche se non sono esplicitamente annotati. Il compilatore è in grado di assegnare implicitamente delle durate.
  • La durata 'static è assegnata ai riferimenti che sono memorizzati nel programma binario e saranno validi per tutta la sua esecuzione. Questo lifetime è in particolare assegnato a stringhe letterali, che hanno il tipo &'static str .

Parametri di funzione (durata dell'input)

fn foo<'a>(x: &'a u32) {
    // ...
}

Questo specifica che foo ha una durata 'a , e il parametro x deve avere una durata almeno di 'a . Le durate delle funzioni vengono generalmente omesse attraverso l' elisione a vita :

fn foo(x: &u32) {
    // ...
}

Nel caso in cui una funzione prende più riferimenti come parametri e restituisce un riferimento, il compilatore non può dedurre la durata del risultato attraverso l' elisione a vita .

error[E0106]: missing lifetime specifier
1 | fn foo(bar: &str, baz: &str) -> &i32 {
  |                                 ^ expected lifetime parameter

Invece, i parametri di durata dovrebbero essere specificati esplicitamente.

// Return value of `foo` is valid as long as `bar` and `baz` are alive.
fn foo<'a>(bar: &'a str, baz: &'a str) -> &'a i32 {

Le funzioni possono richiedere anche più parametri di durata.

// Return value is valid for the scope of `bar`
fn foo<'a, 'b>(bar: &'a str, baz: &'b str) -> &'a i32 {

Struct Fields

struct Struct<'a> {
    x: &'a u32,
}

Questo specifica che ogni data istanza di Struct ha una durata 'a , e il &u32 memorizzato in x deve avere una durata almeno di 'a .

Impl Blocks

impl<'a> Type<'a> {
    fn my_function(&self) -> &'a u32 {
        self.x
    }
}

Questo specifica che Type ha lifetime 'a , e che il riferimento restituito da my_function() potrebbe non essere più valido dopo 'a termina perché il Type non esiste più per contenere self.x

Limiti dei tratti più alti

fn copy_if<F>(slice: &[i32], pred: F) -> Vec<i32>
    where for<'a> F: Fn(&'a i32) -> bool
{
    let mut result = vec![];
    for &element in slice {
        if pred(&element) {
            result.push(element);
        }
    }
    result
}

Questo specifica che il riferimento su i32 nel tratto di tratto Fn può avere una durata qualsiasi.

Quanto segue non funziona:

fn wrong_copy_if<'a, F>(slice: &[i32], pred: F) -> Vec<i32>
    where F: Fn(&'a i32) -> bool
{                                   // <----------------+
    let mut result = vec![];        //       'a scope   |
    for &element in slice {         // <--------+       |
        if pred(&element) {         //          |       |
            result.push(element);   // element's|       |
        }                           //   scope  |       |
    }                               // <--------+       |
    result                          //                  |
}                                   // <----------------+

Il compilatore dà il seguente errore:

error: `element` does not live long enough
if pred(&element) {         //          |       |
         ^~~~~~~

perché la variabile locale element non vive fino a 'a vita (come possiamo vedere dai commenti del codice).

La vita non può essere dichiarata a livello di funzione, perché abbiamo bisogno di un'altra vita. È per questo che abbiamo usato for<'a> : per specificare che il riferimento può essere valido per qualsiasi durata (quindi è possibile utilizzare una durata inferiore).

I limiti dei tratti di livello superiore possono essere utilizzati anche su struct:

struct Window<F>
    where for<'a> F: FnOnce(&'a Window<F>)
{
    on_close: F,
}

così come su altri oggetti.

I limiti dei tratti di rango superiore sono più comunemente usati con i tratti Fn* .

Per questi esempi, la vita elision funziona bene, quindi non dobbiamo specificare la durata.



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