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

67 lines
No EOL
3.8 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.

## 1. Суть трейта `Deref`
Трейт `std::ops::Deref` позволяет кастомизировать поведение оператора разыменования `*`.
Главная цель — сделать **Smart Pointers** (умные указатели) взаимозаменяемыми с обычными ссылками в клиентском коде.
**Механизм работы:**
Когда вы пишете `*y` для типа, реализующего `Deref`, Rust неявно преобразует это в:
rust
`*(y.deref())`
1. Вызывается метод `deref()`, который возвращает **ссылку** на внутреннее значение (`&Target`).
2. Затем происходит обычное разыменование `*` этой полученной ссылки.
> **Важно:** Метод `deref` возвращает именно ссылку, а не значение, чтобы не перемещать (move) владение данными из умного указателя.
## 2. Реализация
Для реализации собственного умного указателя (как в примере `MyBox<T>`) нужно:
- Указать ассоциированный тип `Target` (тип данных внутри обертки).
- Реализовать метод `deref`.
rust
`use std::ops::Deref; impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &Self::Target { &self.0 // Возвращаем ссылку на поле кортежной структуры } }`
## 3. Deref Coercion (Неявное приведение)
Это механизм эргономики Rust, который автоматически преобразует ссылки при передаче аргументов в функции или методы.
- **Как работает:** Если тип `T` реализует `Deref<Target=U>`, то `&T` может быть неявно приведен к `&U`.
- **Цепочки:** Coercion работает рекурсивно.
-ример:_ `&MyBox<String>``deref``&String``deref``&str`.
- Это позволяет передавать `&MyBox<String>` в функцию, ожидающую `&str`.
- **Цена:** Работает на этапе компиляции (compile-time resolution), **runtime оверхеда нет**.
Без этого механизма код превратился бы в нагромождение символов: `&(*m)[..]` вместо простого `&m`.
## 4. Взаимодействие с изменяемостью (Mutability)
Для изменяемых ссылок существует зеркальный трейт `DerefMut`.
**Три правила приведения (Coercion rules):**
Rust применяет приведение типов в следующих случаях:
1. **`&T``&U`**: Если реализован `Deref` (Immutable to Immutable).
2. **`&mut T``&mut U`**: Если реализован `DerefMut` (Mutable to Mutable).
3. **`&mut T``&U`**: Если реализован `Deref` (Mutable to Immutable).
> **Критическое ограничение:** Приведение **Immutable (`&T`) → Mutable (`&mut U`)** невозможно.
> Это нарушило бы правила заимствования (Borrowing Rules), так как нельзя гарантировать уникальность создаваемой изменяемой ссылки, если исходная ссылка была неизменяемой (а их может быть много).
4. [https://doc.rust-lang.org/book/ch15-02-deref.html](https://doc.rust-lang.org/book/ch15-02-deref.html)