Тип ManuallyDrop
Тип ManuallyDrop представляет собой обёртку над значением,
которая предотвращает автоматический вызов деструктора
(метода drop) при выходе переменной из области видимости.
Этот тип полезен в ситуациях, когда необходимо вручную управлять
временем жизни ресурсов, например, при работе с низкоуровневой
памятью или при реализации коллекций. Параметром тип принимает
значение любого типа T, для которого нужно отключить
автоматическую очистку.
Важно понимать, что ManuallyDrop не делает само значение
"безопасным" - он лишь снимает ответственность за вызов
деструктора с компилятора и перекладывает её на программиста.
Если забыть вручную освободить ресурсы, это приведёт к утечке
памяти. Для ручного освобождения обычно используется метод
drop из модуля std::mem или прямое чтение
значения через unsafe.
Синтаксис
use std::mem::ManuallyDrop;
let value = ManuallyDrop::new(data);
Также тип можно использовать в структурах и перечислениях, где он часто применяется для гибкого управления памятью.
Пример
Давайте создадим значение типа ManuallyDrop для строки
и проверим, что деструктор не вызывается автоматически
при выходе из области видимости:
use std::mem::ManuallyDrop;
struct MyStruct
{
name: String,
}
impl Drop for MyStruct
{
fn drop(&mut self)
{
println!("Dropping {}", self.name);
}
}
fn main()
{
let _normal = MyStruct { name: String::from("normal") };
let _manual = ManuallyDrop::new(MyStruct { name: String::from("manual") });
println!("End of main");
}
Результат выполнения кода:
End of main
Dropping normal
Как видите, для переменной _normal деструктор был вызван
автоматически, а для _manual - нет. Это привело к тому,
что сообщение "Dropping manual" не было выведено.
Пример
Давайте вручную освободим ресурс, хранящийся в
ManuallyDrop, используя метод drop:
use std::mem::ManuallyDrop;
struct MyStruct
{
name: String,
}
impl Drop for MyStruct
{
fn drop(&mut self)
{
println!("Dropping {}", self.name);
}
}
fn main()
{
let manual = ManuallyDrop::new(MyStruct { name: String::from("manual") });
println!("Before manual drop");
unsafe
{
ManuallyDrop::drop(&mut manual);
}
println!("After manual drop");
}
Результат выполнения кода:
Before manual drop
Dropping manual
After manual drop
Обратите внимание, что метод ManuallyDrop::drop является
небезопасным, так как после его вызова значение считается
перемещённым, и повторный вызов приведёт к неопределённому
поведению.
Смотрите также
-
ключевое слово
unsafe,
которое позволяет выполнять небезопасные операции -
функция
drop,
которая явно вызывает деструктор значения -
функция
forget,
которая забывает значение без вызова деструктора -
тип
MaybeUninit,
который представляет возможно неинициализированное значение