hyperion/20-dev/00-rust/smart pointers/drop.md
2025-11-27 23:37:40 +03:00

60 lines
No EOL
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Вот краткая выжимка о трейте `Drop` на основе предоставленного материала.
### 1. Суть трейта `Drop`
Трейт `Drop` используется для настройки кода, который **автоматически** выполняется, когда значение выходит из области видимости (scope).
* **Основная цель:** Очистка ресурсов (освобождение памяти в куче, закрытие файлов, сетевых соединений, снятие блокировок).
* Это аналог **деструктора** в ООП языках.
* В Rust почти все умные указатели (например, `Box<T>`) используют `Drop` для корректного освобождения памяти.
### 2. Как реализовать
Нужно реализовать единственный метод `drop`, который принимает мутабельную ссылку на `self`.
```rust
struct CustomSmartPointer {
data: String,
}
impl Drop for CustomSmartPointer {
fn drop(&mut self) {
// Ваш код очистки.
// В примере: просто выводим сообщение.
println!("Dropping CustomSmartPointer with data `{}`!", self.data);
}
}
```
* **Автоматический вызов:** Вам **не нужно** вызывать этот метод вручную. Rust сам вставит вызов в нужном месте (обычно в конце блока `{}`).
* **Порядок:** Переменные удаляются в порядке, **обратном** их созданию (LIFO - Last In, First Out).
### 3. Ручная очистка (Early Drop)
Иногда нужно освободить ресурс *раньше*, чем закончится область видимости (например, чтобы раньше снять блокировку `Mutex` или закрыть файл).
* **Проблема:** Rust **запрещает** вызывать метод `.drop()` вручную (ошибка компиляции `explicit destructor calls not allowed`), чтобы избежать двойной очистки (double free error).
* **Решение:** Используйте функцию `std::mem::drop(value)`. Она принимает значение по значению (забирает владение) и тут же выбрасывает его, вызывая деструктор.
```rust
fn main() {
let c = CustomSmartPointer { data: String::from("some data") };
println!("Created.");
// c.drop(); // ОШИБКА! Нельзя вызывать метод трейта напрямую.
drop(c); // Правильно. Явный вызов функции из std::mem.
// Деструктор отработает здесь.
println!("End of main.");
}
```
### Итог одной строкой
`Drop` позволяет написать код, который выполнится автоматически при уничтожении объекта, а если нужно уничтожить объект досрочно — используйте функцию `std::mem::drop`.
[1](https://doc.rust-lang.ru/book/ch15-03-drop.html)
[2](https://doc.rust-lang.ru/stable/rust-by-example/trait/drop.html)
[3](https://labex.io/ru/tutorials/cleanup-with-rust-s-drop-trait-100433)
[4](https://habr.com/ru/articles/960608/)
[5](https://doc.rust-lang.ru/stable/rust-by-example/generics/gen_trait.html)
[6](https://www.reddit.com/r/rust/comments/uhz9mr/implementing_drop_manually_to_show_progress/)
[7](https://habr.com/ru/articles/277461/)
[8](https://www.youtube.com/watch?v=7ec7hpndex4)
[9](https://doc.rust-lang.org/std/ops/trait.Drop.html)