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

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

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

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

// Эта функция берёт во владение память, выделенную в куче
fn destroy_box(c: Box<i32>) {
    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);
    // ЗАДАНИЕ ^ Попробуйте раскомментировать эту строку
}