Rust на примерах — страница 35 из 65

Анализатор заимствований использует явные аннотации времён жизни для определения того, как долго ссылки будут действительны. В случаях, когда времена жизни не скрыты1, Rust требует их явного аннотирования, чтобы определить какое у ссылки должно быть время жизни. Для явного аннотирования времени жизни используется синтаксис с символом апострофа, как тут:

foo<'a>

// `foo` имеет параметр времени жизни `'a`

Подобно замыканиям, явное использование времён жизни требует обобщённого параметра. Кроме того, такой синтаксис показывает, что время жизни foo не может превышать 'a. Явная аннотация для типа имеет форму &'a T, где 'a уже задана.

В случаях со множественными временами жизни, синтаксис будет подобен следующему:

foo<'a, 'b>

// `foo` имеет параметры времён жизни `'a` и `'b`

В данном случае, время жизни foo не может превышать ни 'a, ни 'b.

Рассмотрим следующий пример, в котором используется явная аннотация времён жизни:

// `print_refs` получает две ссылки на `i32`, имеющие различные

// времена жизни `'a` и `'b`. Оба этих времени жизни должны существовать

// не меньше, чем функция `print_refs`.

fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) {

println!("x равно {} и y равно {}", x, y);

}

// Функция, не имеющая аргументов, но имеющая параметр времени жизни `'a`.

fn failed_borrow<'a>() {

let _x = 12;

// ОШИБКА: `_x` не живёт достаточно долго (`_x` does not live long enough)

//let y: &'a i32 = &_x;

// Попытка использования времени жизни `'a` для явного аннотирования

// внутри функции приведёт к ошибке, так как время жизни у `&_x` короче, чем

// у `y`. Короткое время жизни не может быть приведено к длинному.

}

fn main() {

// Создадим переменные, которые далее будут заимствованы.

let (four, nine) = (4, 9);

// Заимствуем (`&`) обе переменные и передадим их в функцию.

print_refs(&four, &nine);

// Любой ввод, который заимствуется, должен жить дольше, чем заимствующий.

// Другими словами, время жизни `four` и `nine` должно

// быть больше, чем время жизни `print_refs`.

failed_borrow();

// `failed_borrow` не содержит ссылок, заставляющих `'a` быть

// больше, чем время жизни функции, но `'a` больше.

// Поскольку время жизни никогда не ограничено, оно, по умолчанию, равно `'static`.

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

1

сокрытие позволяет скрыть аннотации времён жизни, но они всё же присутствуют.

Смотрите также:

Обобщения и замыкания

Функции

Сигнатуры функции с указанием времени жизни имеют некоторые ограничения:

   • любая ссылка должна иметь аннотированное время жизни

   • любая возвращаемая ссылка должна иметь то же время жизни, что входящая ссылка или static.

Кроме того, обратите внимание, что возврат ссылок из функции, которая не имеет ссылок во входных аргументах, запрещён, если он приведёт к возвращению ссылок на недопустимые данные. В следующем примере показаны некоторые действительные формы функции со временем жизни:

// Одна входная ссылка со временем жизни `'a`, которая

// будет жить как минимум до конца функции.

fn print_one<'a>(x: &'a i32) {

println!("`print_one`: x is {}", x);

}

// Использование времени жизни также возможно с изменяемыми ссылками.

fn add_one<'a>(x: &'a mut i32) {

*x += 1;

}

// Несколько элементов с различными временами жизни. В этом случае

// было бы хорошо, чтобы у обоих ссылок было одно время жизни `'a`,

// в более сложных случаях может потребоваться различное время жизни.

fn print_multi<'a, 'b>(x: &'a i32, y: &'b i32) {

println!("`print_multi`: x is {}, y is {}", x, y);

}

// Возврат переданных на вход ссылок допустим.

// Однако должен быть указано правильное время жизни.

fn pass_x<'a, 'b>(x: &'a i32, _: &'b i32) ->&'a i32 { x }

//fn invalid_output<'a>() ->&'a String { &String::from("foo") }

// Код написанный выше является недопустимым: время жизни `'a`

// должно жить после выхода из функции.

// Здесь, `&String::from("foo")` создает ссылку на `String`

// Данные будут удалены после выхода из области видимости, и

// будет возвращена ссылка на недопустимые данные.

fn main() {

let x = 7;

let y = 9;

print_one(&x);

print_multi(&x, &y);

let z = pass_x(&x, &y);

print_one(z);

let mut t = 3;

add_one(&mut t);

print_one(&t);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Смотрите также:

функции

Методы

Методы аннотируются аналогично функциям:

struct Owner(i32);

impl Owner {

// Время жизни аннотируется как в отдельной функции.

fn add_one<'a>(&'a mut self) { self.0 += 1; }

fn print<'a>(&'a self) {

println!("`print`: {}", self.0);

}

}

fn main() {

let mut owner = Owner(18);

owner.add_one();

owner.print();

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX