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

3.8 KiB
Raw Blame History

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&Stringderef&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), так как нельзя гарантировать уникальность создаваемой изменяемой ссылки, если исходная ссылка была неизменяемой (а их может быть много).

  1. https://doc.rust-lang.org/book/ch15-02-deref.html