Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
借用 / 参照(&)
借用(borrowing)は、所有権を移動させずに値への参照を渡す仕組みです。不変参照(&T)は同時に複数持てますが、可変参照(&mut T)は同時に1つしか持てません。
構文
// 不変参照(読み取り専用)
let r = &変数;
fn 関数名(引数: &型) { ... }
// 可変参照(読み書き可能)
let r = &mut 変数;
fn 関数名(引数: &mut 型) { ... }
借用ルール一覧
| ルール | 概要 |
|---|---|
| 不変参照は複数OK | &T は同時にいくつでも作成できます。 |
| 可変参照は1つのみ | &mut T は同時に1つしか存在できません(データ競合を防ぎます)。 |
| 不変と可変は共存不可 | &T と &mut T を同時に持つことはできません。 |
| ダングリング参照禁止 | 参照は参照先よりも長く生存できません(コンパイラが検証します)。 |
サンプルコード
fn print_length(s: &String) {
println!("長さ: {}", s.len()); // 所有権を借りて読み取るだけです。
}
fn append_world(s: &mut String) {
s.push_str(", world"); // 可変参照で変更できます。
}
fn main() {
let s = String::from("hello");
// 不変参照は複数同時に作れます。
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
print_length(&s); // 所有権は移動しません。
println!("{}", s); // sはまだ使えます。
// 可変参照
let mut s2 = String::from("hello");
append_world(&mut s2);
println!("{}", s2); // 『hello, world』と出力されます。
// 可変参照は同時に1つのみです。
let r3 = &mut s2;
// let r4 = &mut s2; // エラー:可変参照は同時に2つ持てません。
println!("{}", r3);
}
概要
借用チェッカー(borrow checker)はコンパイル時に参照の有効性を検証します。これにより、null参照やダングリングポインタなどの問題が実行前に検出されます。
可変参照と不変参照を同じスコープで同時に使用するとコンパイルエラーになります。ただしRustエディション2018以降では、参照の最後の使用箇所以降であれば新しい参照を作成できる「Non-Lexical Lifetimes(NLL)」が適用されます。
参照の有効期間(ライフタイム)についてはライフタイム('a)を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。