РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
562 of 1245 menu

Трейт DerefMut

Трейт DerefMut определяет поведение оператора изменяемого разыменования * для умных указателей. Если тип реализует DerefMut, то по изменяемой ссылке на этот тип можно получить изменяемую ссылку на внутренние данные и, например, вызывать методы, которые требуют &mut self.

Трейт является продолжением трейта Deref: Deref даёт доступ к данным только для чтения, а DerefMut - ещё и для изменения. Метод deref_mut принимает изменяемую ссылку &mut self и возвращает изменяемую ссылку &mut Self::Target на целевой тип.

Синтаксис

trait DerefMut: Deref { fn deref_mut(&mut self) -> &mut Self::Target; }

Пример

Реализуем простой умный указатель MyBox, который хранит значение и позволяет изменять его через DerefMut. Для этого также потребуется реализовать трейт Deref:

use std::ops::{Deref, DerefMut}; struct MyBox<T>(T); impl<T> MyBox<T> { fn new(x: T) -> MyBox<T> { MyBox(x) } } impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &T { &self.0 } } impl<T> DerefMut for MyBox<T> { fn deref_mut(&mut self) -> &mut T { &mut self.0 } } fn main() { let mut b = MyBox::new(5); *b = 10; println!("{}", *b); }

Результат выполнения кода:

10

Пример

Благодаря DerefMut можно вызывать методы, требующие изменяемую ссылку, прямо через умный указатель. Давайте изменим строку внутри MyBox<String>:

use std::ops::{Deref, DerefMut}; struct MyBox<T>(T); impl<T> MyBox<T> { fn new(x: T) -> MyBox<T> { MyBox(x) } } impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &T { &self.0 } } impl<T> DerefMut for MyBox<T> { fn deref_mut(&mut self) -> &mut T { &mut self.0 } } fn main() { let mut b = MyBox::new(String::from("abcde")); b.push_str("12345"); println!("{}", *b); }

Результат выполнения кода:

"abcde12345"

Пример

Трейт DerefMut часто реализуется для обёрток над векторами. Давайте создадим MyVec и добавим в него элемент через метод push:

use std::ops::{Deref, DerefMut}; struct MyVec<T>(Vec<T>); impl<T> MyVec<T> { fn new() -> MyVec<T> { MyVec(Vec::new()) } } impl<T> Deref for MyVec<T> { type Target = Vec<T>; fn deref(&self) -> &Vec<T> { &self.0 } } impl<T> DerefMut for MyVec<T> { fn deref_mut(&mut self) -> &mut Vec<T> { &mut self.0 } } fn main() { let mut v = MyVec::new(); v.push(1); v.push(2); v.push(3); println!("{:?}", *v); }

Результат выполнения кода:

[1, 2, 3]

Смотрите также

  • трейт Deref,
    который позволяет разыменовывать умный указатель только для чтения
  • трейт trait,
    который описывает общее поведение типов в Rust
  • трейт impl for,
    который позволяет реализовать трейт для конкретного типа
  • трейт trait bound,
    который задаёт ограничения на обобщённые типы
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить