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