Ключевое слово move
Ключевое слово move применяется при создании
замыканий в Rust. По умолчанию замыкание захватывает
переменные из окружения по ссылке или изменяемой ссылке,
если это возможно. Однако при использовании move
замыкание принудительно забирает владение всеми
используемыми переменными, перемещая их внутрь себя.
Это особенно важно при передаче замыкания в другой поток
или при возврате замыкания из функции, когда время жизни
исходных переменных может закончиться раньше, чем
замыкание будет вызвано.
Синтаксис
move || {
// тело замыкания
}
Также ключевое слово move может использоваться
перед блоком, например при работе с асинхронными
блоками:
move async {
// тело асинхронного блока
}
Пример
Давайте создадим замыкание без move и посмотрим,
как оно захватывает переменную по ссылке:
fn main()
{
let s = String::from("abcde");
let closure = || println!("{}", s);
closure();
println!("{}", s);
}
Результат выполнения кода:
abcde
abcde
Как видите, переменная s осталась доступной
после вызова замыкания, потому что оно захватило её
по ссылке.
Пример
Теперь используем move, чтобы замыкание
забрало владение переменной:
fn main()
{
let s = String::from("abcde");
let closure = move || println!("{}", s);
closure();
}
Результат выполнения кода:
abcde
В этом случае переменная s перемещается внутрь
замыкания. Попытка использовать s после
определения замыкания вызовет ошибку компиляции.
Пример
Рассмотрим практический пример с потоком, где
move необходим для передачи владения:
use std::thread;
fn main()
{
let s = String::from("12345");
let handle = thread::spawn(move || {
println!("{}", s);
});
handle.join().unwrap();
}
Результат выполнения кода:
12345
Без move этот код не скомпилировался бы,
так как поток может пережить переменную s
в основной функции.
Пример
Ключевое слово move также позволяет
возвращать замыкание из функции:
fn create_closure() -> impl Fn()
{
let s = String::from("abcde");
move || println!("{}", s)
}
fn main()
{
let closure = create_closure();
closure();
}
Результат выполнения кода:
abcde
Здесь move обязателен, потому что локальная
переменная s уничтожится при выходе из функции,
а замыкание продолжит существовать.
Смотрите также
-
ключевое слово
closure,
которое создаёт анонимные функции -
ключевое слово
move-closure,
которое описывает замыкания с перемещением -
ключевое слово
fn,
которое объявляет функции -
ключевое слово
let,
которое связывает значение с переменной