サーチ…
前書き
構文
- 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
いずれも指定しない場合、関数は引数の所有権を取得すると言います。つまり、 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