Введение
В этом лабе мы обсудим концепцию 'static в Rust.
Примечание: Если в лабе не указано имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать
main.rs, скомпилировать и запустить его с помощьюrustc main.rs &&./main.
Статическое время жизни ('static)
В Rust есть несколько зарезервированных имен для времени жизни. Одно из них - 'static. Вы можете встретить его в двух ситуациях:
// Ссылка с временем жизни `'static`:
let s: &'static str = "hello world";
// `'static` в качестве части ограничения трейта:
fn generic<T>(x: T) where T: 'static {}
Обе ситуации связаны, но имеют незначительные различия, и это часто вызывает путаницу при изучении Rust. Вот несколько примеров для каждой ситуации:
Время жизни ссылки
В качестве времени жизни ссылки 'static указывает на то, что данные, на которые указывает ссылка, существуют на протяжении всей жизни исполняемой программы. Её можно по-прежнему привести к более короткому времени жизни.
Есть два способа создать переменную с временем жизни 'static, и обе они хранятся в只读 памяти бинарника:
- Создать константу с объявлением
static. - Создать
string-литерал, который имеет тип:&'static str.
Посмотрите на следующий пример, демонстрирующий каждый метод:
// Создать константу с временем жизни `'static`.
static NUM: i32 = 18;
// Возвращает ссылку на `NUM`, где её время жизни `'static`
// приводится к времени жизни входного аргумента.
fn coerce_static<'a>(_: &'a i32) -> &'a i32 {
&NUM
}
fn main() {
{
// Создать `string`-литерал и вывести его:
let static_string = "I'm in read-only memory";
println!("static_string: {}", static_string);
// Когда `static_string` выходит из области видимости, ссылка
// больше не может быть использована, но данные остаются в бинарнике.
}
{
// Создать целое число для использования в `coerce_static`:
let lifetime_num = 9;
// Привести время жизни `NUM` к времени жизни `lifetime_num`:
let coerced_static = coerce_static(&lifetime_num);
println!("coerced_static: {}", coerced_static);
}
println!("NUM: {} остаётся доступной!", NUM);
}
Ограничение трейта
В качестве ограничения трейта это означает, что тип не содержит никаких ссылок, время жизни которых не статично. Например, владелец может держать тип столько времени, сколько ему нужно, и он никогда не станет недействительным, пока владелец не уничтожит его.
Важно понять, что это означает, что любые собственные данные всегда проходят ограничение времени жизни 'static, но ссылка на эти собственные данные обычно не проходит:
use std::fmt::Debug;
fn print_it( input: impl Debug + 'static ) {
println!( "'static value passed in is: {:?}", input );
}
fn main() {
// i является собственным и не содержит ссылок, поэтому оно имеет время жизни `'static`:
let i = 5;
print_it(i);
// оops, &i имеет время жизни, определённое областью видимости
// main(), поэтому оно не имеет времени жизни `'static`:
print_it(&i);
}
Компилятор сообщит вам:
error[E0597]: `i` does not live long enough
--> src/lib.rs:15:15
|
15 | print_it(&i);
| ---------^^--
| | |
| | borrowed value does not live long enough
| argument requires that `i` is borrowed for `'static`
16 | }
| - `i` dropped here while still borrowed
Резюме
Поздравляем! Вы завершили лабу по статическим переменным (Static). Вы можете практиковаться в других лабах в LabEx, чтобы улучшить свои навыки.