Опускание lifetime
Опускание lifetime - это правило, по которому компилятор Rust
автоматически расставляет времена жизни в сигнатурах функций,
методов и блоков impl, если они не указаны явно.
Это позволяет писать более короткий и читаемый код без потери
строгости проверки заимствований. Параметров у этого механизма
нет - это набор правил, применяемых компилятором во время
анализа кода.
Опускание lifetime работает по трём основным правилам.
Первое: каждый параметр-ссылка в функции получает своё
собственное время жизни. Второе: если в функции ровно один
входной параметр-ссылка, то время жизни выхода приравнивается
к времени жизни этого параметра. Третье: если входных
параметров-ссылок несколько, но один из них - &self
или &mut self, то время жизни выхода приравнивается
к времени жизни self.
Синтаксис
// Явное указание времени жизни
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str
// Опускание времени жизни
fn longest(x: &str, y: &str) -> &str
Пример
Давайте рассмотрим функцию, которая принимает одну ссылку и возвращает ссылку. Благодаря правилу опускания компилятор сам понимает, что время жизни выхода совпадает со временем жизни входа:
fn first_word(s: &str) -> &str
{
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate()
{
if item == b' '
{
return &s[0..i];
}
}
&s[..]
}
fn main()
{
let text = "abcde 12345";
let res = first_word(text);
println!("{}", res);
}
Результат выполнения кода:
"abcde"
Пример
Если входных ссылок несколько, но одна из них - &self,
компилятор привязывает время жизни выхода к self.
Это часто встречается в методах:
struct Holder
{
value: String,
}
impl Holder
{
fn get_value(&self) -> &str
{
&self.value
}
}
fn main()
{
let h = Holder { value: String::from("12345") };
let res = h.get_value();
println!("{}", res);
}
Результат выполнения кода:
"12345"
Пример
Если входных ссылок несколько и среди них нет self,
компилятор не может вывести время жизни выхода - потребуется
указать его явно. Такой код не скомпилируется:
fn longest(x: &str, y: &str) -> &str
{
if x.len() > y.len()
{
x
}
else
{
y
}
}
fn main()
{
let res = longest("abcde", "12345");
println!("{}", res);
}
Чтобы код заработал, нужно явно указать время жизни:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str
{
if x.len() > y.len()
{
x
}
else
{
y
}
}
fn main()
{
let res = longest("abcde", "12345");
println!("{}", res);
}
Результат выполнения кода:
"abcde"
Смотрите также
-
ключевое слово
lifetime,
которое задаёт время жизни ссылок явно -
ключевое слово
static lifetime,
которое обозначает время жизни всей программы -
механизм
multiple lifetimes,
который позволяет использовать несколько времён жизни -
механизм
fn lifetime,
который описывает времена жизни в сигнатурах функций