サーチ…


前書き

所有権はRustの最も重要な概念の1つであり、他のほとんどの言語では存在しないものです。特定の変数によって値を所有できるという考え方は、特にコピーが暗黙の言語では理解しにくいことがよくありますが、このセクションでは所有権を取り巻くさまざまな考え方について検討します。

構文

  • x:&T = ... // xは不変の参照です
  • let x:&mut T = ... // xは排他的で変更可能な参照です
  • let = =&mut foo; // fooを可変的に借りる(すなわち排他的に)
  • let = =&foo; // fooを永久に借りる
  • let = = foo; // fooを移動する(所有権が必要)

備考

  • 旧バージョンのRust(1.0より前、2015年5月)では、所有変数の型が~始まっていました。これは非常に古い例で見ることができます。

所有権と借入

Rustのすべての値には、正確に1人の所有者がいます。所有者は、範囲外になったときにその値を落とす責任があり、その値の所有権を移動できる唯一の者です。値の所有者は、他のコードがその値を借用することによって、値の所有者に参照を渡すことができます。任意の時点で、値に対する不変な参照の数に制限はありません。

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いずれも指定しない場合、関数は引数の所有権を取得すると言います。つまり、 fooxを落とす責任も負うことになります。

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( boolusizef64など)のほとんどのプリミティブはCopyです。

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

特に、 VecStringCopyはありません

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