Rust на примерах — страница 32 из 65

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. Деструктор вызывается, когда ресурс выходит за пределы области видимости. Этот типаж не требуется реализовать для каждого типа. Реализовать его для вашего типа вам потребуется, только если требуется своя логика при удалении экземпляра типа.

Выполните пример ниже, чтобы увидеть, как работает типаж Drop. Когда переменная в функции main выходит за пределы области действия, будет вызван пользовательский деструктор.

struct ToDrop;

impl Drop for ToDrop {

fn drop(&mut self) {

println!("ToDrop is being dropped");

}

}

fn main() {

let x = ToDrop;

println!("Made a ToDrop!");

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

Упаковка

Владение и перемещение

Поскольку переменные ответственны за освобождение своих ресурсов, ресурсы могут иметь лишь одного владельца. Это ограничение предотвращает возможность высвобождения ресурсов более одно раза. Обратите внимание, что не все переменные владеют своим ресурсом (например, ссылки).

При присваивании (let x = y) или при передаче функции аргумента по значению (foo(x)), владение ресурсами передаётся. В языке Rust это называется перемещением.

После перемещения ресурсов, переменная, владевшая ресурсами ранее, не может быть использована. Это предотвращает создание висячих указателей.

// Эта функция берёт во владение память, выделенную в куче

fn destroy_box(c: Box) {

println!("Уничтожаем упаковку, в которой хранится {}", c);

// `c` уничтожится, а память будет освобождена

}

fn main() {

// Целое число выделенное в стеке

let x = 5u32;

// *Копируем* `x` в `y`. В данном случае нет ресурсов для перемещения

let y = x;

// Оба значения можно использовать независимо

println!("x равен {}, а y равен {}", x, y);

// `a` - указатель на целое число, выделенное в куче

let a = Box::new(5i32);

println!("a содержит: {}", a);

// *Перемещаем* `a` в `b`

let b = a;

// Адрес указателя `a` копируется (но не данные) в `b`.

// Оба указателя указывают на одни и те же данные в куче, но

// `b` теперь владеет ими.

// Ошибка! `a` больше не может получить доступ к данным, потому что

// больше не владеет данными в куче.

//println!("a содержит: {}", a);

// ЗАДАНИЕ ^ Попробуйте раскомментировать эту строку

// Эта функция берет во владение память, выделенную в куче, которой ранее владела `b`

destroy_box(b);

// Поскольку в данный момент память в куче уже освобождена, это действие

// приведёт к разыменованию освобождённой памяти, но это запрещено компилятором

// Ошибка! Причина та же, что и в прошлый раз

//println!("b содержит: {}", b);

// ЗАДАНИЕ ^ Попробуйте раскомментировать эту строку

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Изменяемость

Изменяемость данных может быть изменена при передаче владения.

fn main() {

let immutable_box = Box::new(5u32);

println!("immutable_box содержит в себе {}", immutable_box);

// Ошибка изменяемости

//*immutable_box = 4;

// *Переместить* упаковку, изменив её владение (и изменяемость)

let mut mutable_box = immutable_box;

println!("mutable_box содержит в себе {}", mutable_box);

// Изменяем данные внутри упаковки

*mutable_box = 4;

println!("mutable_box now содержит в себе {}", mutable_box);