Introduction
A lifetime is a construct the compiler (or more specifically, its borrow checker) uses to ensure all borrows are valid.
Specifically, a variable’s lifetime begins when it is created and ends when it is destroyed. While lifetimes and scopes are often referred to together, they are not the same.
Take, for example, the case where we borrow a variable via &. The borrow has a lifetime that is determined by where it is declared.
As a result, the borrow is valid as long as it ends before the lender is destroyed. However, the scope of the borrow is determined by where the reference is used.
showcase:
1 | // Lifetimes are annotated below with lines denoting the creation |
Note that no names or types are assigned to label lifetimes. This restricts how lifetimes will be able to be used as we will see.
需要注意的是,lifetime需要开发人员自己去标记出来,IDE并不会帮助你标记一个变量的lifetime。
从上面的代码可知,i的lifetime和scope的周期完全不同,scope周期 <= lifetime周期。
Elision annotation
Some lifetime patterns are overwhelmingly(强制地) common and so the borrow checker will implicitly add them to save typing and to improve readability. This process of implicit addition is called elision. Elision exists in Rust solely because these patterns are common.
The following code shows a few examples of elision. For a more comprehensive description of elision
1 | // `elided_input` and `annotated_input` essentially have identical signatures |
Functions
Ignoring elision, function signatures with lifetimes have a few constraints:
- any reference must have an annotated lifetime.
- any reference being returned must have the same lifetime as an input or be static.
Additionally, note that returning references without input is banned if it would result in returning references to invalid data. The following example shows off(强调) some valid forms of functions with lifetimes:
1 | // One input reference with lifetime `'a` which must live |
如果function有返回值,则返回值必须声明lifetime。
Example
Case: Explicit annotation
1 | // `print_refs` takes two references to `i32` which have different |