Поиск…


Вступление

Собственность - одна из самых важных концепций в Rust, и это то, чего нет на большинстве других языков. Идея о том, что ценность может принадлежать определенной переменной, часто довольно трудно понять, особенно в языках, где копирование является неявным, но в этом разделе будут рассмотрены различные идеи, связанные с владением.

Синтаксис

  • пусть x: & T = ... // x - неизменяемая ссылка
  • пусть x: & mut T = ... // x - исключительная, изменяемая ссылка
  • пусть _ = & mut foo; // заимствовать foo изменчиво (т. е. исключительно)
  • пусть _ = & foo; // заимствовать foo неизменно
  • пусть _ = foo; // перемещение foo (требуется владение)

замечания

  • В гораздо более ранних версиях Rust (до 1.0, май 2015 г.) у принадлежащей переменной был тип, начинающийся с ~ . Вы можете увидеть это в очень старых примерах.

Собственность и займы

Все значения в Rust имеют ровно один владелец. Владелец несет ответственность за удаление этого значения, когда он выходит за пределы области действия, и является единственным, кто может переместить право собственности на это значение. Владелец значения может отдать ссылки на него, разрешив другим частям кода занять это значение. В любой момент времени может быть любое количество неизменяемых ссылок на значение:

let owned = String::from("hello");
// since we own the value, we may let other variables borrow it
let immutable_borrow1 = &owned;
// as all current borrows are immutable, we can allow many of them
let immutable_borrow2 = &owned;
// in fact, if we have an immutable reference, we are also free to
// duplicate that reference, since we maintain the invariant that
// there are only immutable references
let immutable_borrow3 = &*immutable_borrow2;

или одну изменяемую ссылку на нее ( ERROR обозначает ошибку времени компиляции):

// for us to borrow a value mutably, it must be mutable
let mut owned = String::from("hello");
// we can borrow owned mutably
let mutable_borrow = &mut owned;
// but note that we cannot borrow owned *again*
let mutable_borrow2 = &mut owned; // ERROR, already borrowed
// nor can we cannot borrow owned immutably
// since a mutable borrow is exclusive.
let immutable_borrow = &owned; // ERROR, already borrowed

Если к значению имеются невыполненные ссылки (изменяемые или неизменяемые), это значение не может быть перемещено (т. Е. Его собственность отдана). Мы должны были бы убедиться, что все ссылки были отброшены первым, чтобы разрешить перемещать значение:

let foo = owned; // ERROR, outstanding references to owned
let owned = String::from("hello");
{
    let borrow = &owned;
    // ...
} // the scope ends the borrow
let foo = owned; // OK, owned and not borrowed

Периодичность и продолжительность жизни

Все значения в Rust имеют всю жизнь . Время жизни значения охватывает сегмент кода от значения, вводимого туда, где он перемещен, или конец области сложения

{
    let x = String::from("hello"); //             +
    // ...                                        :
    let y = String::from("hello"); //      +      |
    // ...                                 :      :
    foo(x) // x is moved                   |      = x's lifetime
    // ...                                 :
} //                                       = y's lifetime

Всякий раз, когда вы заимствуете значение, результирующая ссылка имеет срок службы , привязанный к времени жизни заимствованного значения:

{
    let x = String::from("hello");
    let y = String::from("world");
    // when we borrow y here, the lifetime of the reference
    // stored in foo is equal to the lifetime of y
    // (i.e., between let y = above, to the end of the scope below)
    let foo = &y;
    // similarly, this reference to x is bound to the lifetime
    // of x --- bar cannot, for example, spawn a thread that uses
    // the reference beyond where x is moved below.
    bar(&x);
}

Звонки и вызов функций

Большинство вопросов о собственности возникают при написании функций. Когда вы указываете типы аргументов функции, вы можете выбрать способ передачи этого значения. Если вам нужен только доступ только для чтения, вы можете взять неизменяемую ссылку:

fn foo(x: &String) {
    // foo is only authorized to read x's contents, and to create
    // additional immutable references to it if it so desires.
    let y = *x; // ERROR, cannot move when not owned
    x.push_str("foo"); // ERROR, cannot mutate with immutable reference
    println!("{}", x.len()); // reading OK
    foo(x); // forwarding reference OK
}

Если foo необходимо изменить аргумент, он должен взять исключительную, изменяемую ссылку:

fn foo(x: &mut String) {
    // foo is still not responsible for dropping x before returning,
    // nor is it allowed to. however, foo may modify the String.
    let x2 = *x; // ERROR, cannot move when not owned
    x.push_str("foo"); // mutating OK
    drop(*x); // ERROR, cannot drop value when not owned
    println!("{}", x.len()); // reading OK
}

Если вы не укажете ни & или &mut , вы говорите, что функция будет владеть аргументом. Это означает, что foo теперь также несет ответственность за удаление x .

fn foo(x: String) {
    // foo may do whatever it wishes with x, since no-one else has
    // access to it. once the function terminates, x will be dropped,
    // unless it is moved away when calling another function.
    let mut x2 = x; // moving OK
    x2.push_str("foo"); // mutating OK
    let _ = &mut x2; // mutable borrow OK
    let _ = &x2; // immutable borrow OK (note that &mut above is dropped)
    println!("{}", x2.len()); // reading OK
    drop(x2); // dropping OK
}

Собственность и свойство копирования

Некоторые типы Rust реализуют свойство Copy . Типы, которые являются Copy могут быть перемещены без использования соответствующего значения. Это связано с тем, что содержимое значения можно просто скопировать по байтам в память для получения нового идентичного значения. Большинство примитивов в Rust ( bool , usize , f64 и т. Д.) - это Copy .

let x: isize = 42;
let xr = &x;
let y = *xr; // OK, because isize is Copy
// both x and y are owned here

Примечательно, что Vec и String не Copy :

let x = Vec::new();
let xr = &x;
let y = *xr; // ERROR, cannot move out of borrowed content


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow