Rust распределяет все по стеку по умолчанию. Вы можете хранить вещи в куче, оборачивая их в умные указатели, такие как Box . Такие типы, как Vec и String, неявно помогают распределению кучи. Умные указатели реализуют черты, перечисленные в таблице ниже. Эти черты умных указателей отличают их от обычной структуры —
Sr.No | Название черты | Пакет и описание |
---|---|---|
1 | Deref |
СТД :: опс :: Deref Используется для неизменяемых операций разыменования, например * v. |
2 | Капля |
СТД :: опс :: Капля Используется для запуска некоторого кода, когда значение выходит из области видимости. Это иногда называют деструктором |
СТД :: опс :: Deref
Используется для неизменяемых операций разыменования, например * v.
СТД :: опс :: Капля
Используется для запуска некоторого кода, когда значение выходит из области видимости. Это иногда называют деструктором
В этой главе мы узнаем о умном указателе Box . Мы также узнаем, как создать собственный умный указатель, такой как Box.
коробка
Умный указатель Box, также называемый ящиком, позволяет хранить данные в куче, а не в стеке. Стек содержит указатель на данные кучи. У Box нет потери производительности, кроме хранения данных в куче.
Давайте посмотрим, как использовать ящик для хранения значения i32 в куче.
fn main() { let var_i32 = 5; //stack let b = Box::new(var_i32); //heap println!("b = {}", b); }
Выход
b = 5
Чтобы получить доступ к значению, указанному переменной, используйте разыменование. * Используется в качестве оператора разыменования. Давайте посмотрим, как использовать разыменование с Box.
fn main() { let x = 5; //value type variable let y = Box::new(x); //y points to a new value 5 in the heap println!("{}",5==x); println!("{}",5==*y); //dereferencing y }
Переменная x является типом значения со значением 5. Таким образом, выражение 5 == x вернет true. Переменная y указывает на кучу. Чтобы получить доступ к значению в куче, нам нужно разыменовать, используя * y. * y возвращает значение 5. Таким образом, выражение 5 == * y возвращает true.
Выход
true true
Иллюстрация — Черта Дерефа
Черта Deref, предоставляемая стандартной библиотекой, требует от нас реализации одного метода с именем deref , который заимствует self и возвращает ссылку на внутренние данные. В следующем примере создается структура MyBox , которая является универсальным типом. В нем реализована черта Дерефа . Эта особенность помогает нам получить доступ к значениям кучи, заключенным в y, используя * y .
use std::ops::Deref; struct MyBox<T>(T); impl<T> MyBox<T> { // Generic structure with static method new fn new(x:T)-> MyBox<T> { MyBox(x) } } impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &T { &self.0 //returns data } } fn main() { let x = 5; let y = MyBox::new(x); // calling static method println!("5==x is {}",5==x); println!("5==*y is {}",5==*y); // dereferencing y println!("x==*y is {}",x==*y); //dereferencing y }
Выход
5==x is true 5==*y is true x==*y is true
Иллюстрация — Drop Trait
Черта Drop содержит метод drop () . Этот метод вызывается, когда структура, которая реализовала эту черту, выходит из области видимости. В некоторых языках программист должен вызывать код для освобождения памяти или ресурсов каждый раз, когда они заканчивают использовать экземпляр умного указателя. В Rust вы можете добиться автоматического освобождения памяти, используя черту Drop.
use std::ops::Deref; 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> Drop for MyBox<T>{ fn drop(&mut self){ println!("dropping MyBox object from memory "); } } fn main() { let x = 50; MyBox::new(x); MyBox::new("Hello"); }
В приведенном выше примере метод drop будет вызываться дважды, когда мы создаем два объекта в куче.