let one_foot: Length<Inch> = Length(12.0, PhantomData);
// `one_meter` имеет параметр фантомного типа `Mm`.
let one_meter: Length<Mm> = Length(1000.0, PhantomData);
// `+` вызывает метод `add()`, который мы реализовали для `Length<Unit>`.
//
// Так как `Length` реализует `Copy`, `add()` не поглощает
// `one_foot` и `one_meter`, а копирует их в `self` и `rhs`.
let two_feet = one_foot + one_foot;
let two_meters = one_meter + one_meter;
// Сложение работает.
println!("один фут + один фут = {:?} фута", two_feet.0);
println!("один метр + один метр = {:?} метра", two_meters.0);
// Бессмысленные операции потерпят неудачу, как и должно быть:
// Ошибка времени компиляции: несоответствие типов.
//let one_feter = one_foot + one_meter;
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Заимствование (&), ограничения (X: Y), перечисления, impl & self, перегрузка, ref, типажи (X for Y) и кортежные структуры.
Области видимости играют важную роль во владении, заимствовании и времени жизни. То есть, они указывают компилятору, когда заимствования действительны, когда ресурсы могут быть освобождены, и когда переменные создаются или уничтожаются.
Переменные в Rust не только держат данные в стеке, они также могут владеть ресурсами; к примеру, Box<T> владеет памятью в куче. Поскольку Rust строго придерживается идиоме RAII, то когда объект выходит за зону видимости, вызывается его деструктор, а ресурс, которым он владеет освобождается.
Такое поведение защищает от багов, связанных с утечкой ресурсов. Вам больше никогда не потребуется вручную освобождать память или же беспокоиться об её утечках! Небольшой пример:
// raii.rs
fn create_box() {
// Выделить память для целого число в куче
let _box1 = Box::new(3i32);
// `_box1` здесь уничтожается, а память освобождается
}
fn main() {
// Выделить память для целого числа в куче
let _box2 = Box::new(5i32);
// Вложенная область видимости:
{
// Выделить память для ещё одного целого числа в куче
let _box3 = Box::new(4i32);
// `_box3` здесь уничтожается, а память освобождается
}
// Создаём большое количество упаковок. Просто потому что можем.
// Здесь нет необходимости освобождать память вручную!
for _ in 0u32..1_000 {
create_box();
}
// `_box2` здесь уничтожается, а память освобождается
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Конечно, мы можем убедиться, что в нашей программе нет ошибок с памятью, используя valgrind:
$ rustc raii.rs && valgrind ./raii
==26873== Memcheck, a memory error detector
==26873== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==26873== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==26873== Command: ./raii
==26873==
==26873==
==26873== HEAP SUMMARY:
==26873== in use at exit: 0 bytes in 0 blocks
==26873== total heap usage: 1,013 allocs, 1,013 frees, 8,696 bytes allocated
==26873==
==26873== All heap blocks were freed -- no leaks are possible
==26873==
==26873== For counts of detected and suppressed errors, rerun with: -v
==26873== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
Утечки отсутствуют!
Понятие деструктора в Rust обеспечивается через типаж Drop. Деструктор вызывается, когда ресурс выходит за пределы области видимости. Этот типаж не требуется реализовать для каждого типа. Реализовать его для вашего типа вам потребуется, только если требуется своя логика при удалении экземпляра типа.