Zoeken…
Syntaxis
- fn-functie <'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> Trait <' a> voor Type
- impliceer <'a> eigenschap voor type <' 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 } }
Opmerkingen
- Alle referenties in Rust hebben een levensduur, zelfs als ze niet expliciet zijn geannoteerd. De compiler kan impliciet levens toewijzen.
- De
'static
levensduur' wordt toegewezen aan referenties die zijn opgeslagen in het binaire programma en zijn geldig gedurende de gehele uitvoering. Deze levensduur wordt met name toegewezen aan stringliterals, die het type&'static str
.
Functieparameters (invoerlevensduur)
fn foo<'a>(x: &'a u32) {
// ...
}
Dit geeft aan dat foo
levensduur 'a
heeft en de parameter x
moet een levensduur hebben van minimaal 'a
. Functielevensduren worden meestal weggelaten door levenslange eliminatie :
fn foo(x: &u32) {
// ...
}
In het geval dat een functie meerdere referenties als parameters gebruikt en een referentie retourneert, kan de compiler de levensduur van het resultaat niet afleiden via levenslange eliminatie .
error[E0106]: missing lifetime specifier
1 | fn foo(bar: &str, baz: &str) -> &i32 {
| ^ expected lifetime parameter
In plaats daarvan moeten de levensduurparameters expliciet worden gespecificeerd.
// 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 {
Functies kunnen ook meerdere levensduurparameters aannemen.
// Return value is valid for the scope of `bar`
fn foo<'a, 'b>(bar: &'a str, baz: &'b str) -> &'a i32 {
Struct Velden
struct Struct<'a> {
x: &'a u32,
}
Dit geeft aan dat elk gegeven exemplaar van Struct
een levensduur heeft 'a
, en de &u32
opgeslagen in x
moet een levensduur hebben van minimaal 'a
.
Impl blokken
impl<'a> Type<'a> {
fn my_function(&self) -> &'a u32 {
self.x
}
}
Dit geeft aan dat Type
levensduur 'a
heeft en dat de referentie die wordt geretourneerd door my_function()
mogelijk niet langer geldig is na 'a
omdat het Type
niet langer bestaat om self.x
.
Hogere eigenschapsgrenzen
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
}
Dit geeft aan dat de referentie op i32 in de Fn
eigenschapsgrens elke levensduur kan hebben.
Het volgende werkt niet:
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 // |
} // <----------------+
De compiler geeft de volgende foutmelding:
error: `element` does not live long enough
if pred(&element) { // | |
^~~~~~~
omdat het element
lokale variabele leeft niet zo lang als de 'a
lifetime (zoals we kunnen zien in de opmerkingen van de code).
De levensduur kan niet worden gedeclareerd op functieniveau, omdat we een andere levensduur nodig hebben. Daarom hebben we for<'a>
: om aan te geven dat de referentie geldig kan zijn voor elke levensduur (vandaar dat een kleinere levensduur kan worden gebruikt).
Hogere karaktertrekgrenzen kunnen ook worden gebruikt op structs:
struct Window<F>
where for<'a> F: FnOnce(&'a Window<F>)
{
on_close: F,
}
evenals op andere items.
Kenmerkgrenzen van hogere rang worden meestal gebruikt met de Fn*
-kenmerken.
Voor deze voorbeelden werkt de levenslange verkiezing prima, dus we hoeven de levensduren niet te specificeren.