Функция drop
Функция drop принудительно уничтожает переданное значение,
вызывая его деструктор (реализацию трейта Drop) и освобождая
связанные с ним ресурсы. Параметром функция принимает значение,
которое нужно уничтожить. Значение передаётся по владению, поэтому
после вызова drop переменная становится недоступной для
дальнейшего использования. Функция находится в модуле
std::mem, но благодаря прелюдии доступна без явного импорта.
Обычно деструкторы вызываются автоматически при выходе переменной
из области видимости. Функция drop позволяет уничтожить
значение досрочно - например, чтобы освободить мьютекс или
закрыть файл раньше конца блока. Важно: drop запрещено
вызывать для типов, реализующих трейт Copy, поскольку
такие значения копируются, а не перемещаются.
Синтаксис
std::mem::drop(value)
Пример
Давайте принудительно уничтожим строку "abcde" до конца
области видимости и убедимся, что деструктор сработал:
struct MyBox
{
name: String,
}
impl Drop for MyBox
{
fn drop(&mut self)
{
println!("dropping {}", self.name);
}
}
fn main()
{
let item = MyBox { name: String::from("abcde") };
println!("before drop");
drop(item);
println!("after drop");
}
Результат выполнения кода:
before drop
dropping abcde
after drop
Пример
Давайте сравним поведение значения, уничтоженного через drop,
и значения, уничтоженного автоматически при выходе из блока:
struct MyBox
{
name: String,
}
impl Drop for MyBox
{
fn drop(&mut self)
{
println!("dropping {}", self.name);
}
}
fn main()
{
let a = MyBox { name: String::from("12345") };
let b = MyBox { name: String::from("abcde") };
drop(a);
println!("between");
}
Результат выполнения кода:
dropping 12345
between
dropping abcde
Значение a уничтожается сразу при вызове drop,
а значение b - автоматически в конце функции main.
Пример
Давайте освободим мьютекс досрочно с помощью drop,
чтобы другой поток мог захватить блокировку:
use std::sync::Mutex;
fn main()
{
let data = Mutex::new(vec![1, 2, 3, 4, 5]);
let guard = data.lock().unwrap();
println!("locked");
drop(guard);
println!("unlocked");
let guard2 = data.lock().unwrap();
println!("{:?}", *guard2);
}
Результат выполнения кода:
locked
unlocked
[1, 2, 3, 4, 5]
Смотрите также
-
функция
drop_in_place,
которая уничтожает значение по сырому указателю -
функция
forget,
которая забывает значение без вызова деструктора -
функция
needs_drop,
которая проверяет, нужен ли типу деструктор -
тип
ManuallyDrop,
который позволяет управлять вызовом деструктора вручную