Closed6
[Rust] 参照・借用のルール
#1 すでに誰かが借用している場合、元の値の破棄や所有権移転はできない
Rust
let s1 = String::from("hello");
let r = &s1; // 参照 `r` を作成
let s2 = s1; // `s2` へ所有権移転
println!("r: {}", r); // <-- コンパイルエラー
error[E0505]: cannot move out of `s1` because it is borrowed
# エラー[E0505]: 借用されているため `s1` からムーブはできません
--> src/main.rs:5:14
|
4 | let r = &s1;
| --- borrow of `s1` occurs here
5 | let s2 = s1;
| ^^ move out of `s1` occurs here
# (2) その前にここで `s1` からムーブされています
6 |
7 | println!("r: {}", r);
| - borrow later used here
# (1) ここで借用している(=参照を使っている)にもかかわらず、↑
理由: 参照が指し示している変数がすでに所有権を失っている(=値を持っていない)事態を防ぐため。
#2 可変参照は同時に 1 つしか持つことができない
Rust
// 可変文字列
let mut s = String::from("hello");
// 可変参照 その 1
let r1 = &mut s;
// 可変参照 その 2
let r2 = &mut s; // <-- コンパイルエラー
println!("{}, {}", r1, r2);
error[E0499]: cannot borrow `s` as mutable more than once at a time
# エラー[E0499]: 可変として `s` を借用することは同時に 1 回しかできません
--> src/main.rs:8:14
|
6 | let r1 = &mut s;
| ------ first mutable borrow occurs here
8 | let r2 = &mut s;
| ^^^^^^ second mutable borrow occurs here
# 可変としての 2 回目の借用が発生しています
9 |
10 | println!("{}, {}", r1, r2);
| -- first borrow later used here
理由: 複数の参照でそれぞれ値を変更されてしまうと、コンパイラがそれを追ってチェックできなくなってしまうため。
#3 初期化されていない変数を借用することはできない
Rust
fn print_string(s2: &String) {
println!("{}", s2);
}
fn main() {
// 初期化してない String 型変数
let s: String;
print_string(&s); // <-- コンパイルエラー
}
error[E0381]: borrow of possibly-uninitialized variable: `s`
# エラー[E0381]: 初期化されていないと思われる変数 `s` から借用しています
--> src/main.rs:8:18
|
8 | print_string(&s);
| ^^ use of possibly-uninitialized `s`
理由: #1 と同様、参照が指し示している変数が値を持っていない事態を防ぐため。
#4 どこも指し示さない(=ダングリング)参照は作成できない
Rust
// 参照を返す関数
fn dangling_fn() -> &String { // <-- コンパイルエラー
let s = String::from("hello");
&s
// ここで dangling_fn() のスコープが終了して
// 変数 `s` はドロップ(破棄)されるため、
// これの参照である `&s` はどこも指さない
}
理由: #1, #3 と同様。
#5 不変参照がある間は、可変参照を作成できない
let mut s = String::from("hello");
let r1 = &s; // 問題なし
let r2 = &s; // 問題なし
let r3 = &mut s; // 大問題!
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as
immutable
# エラー[E0502]: `s`は不変で借用されているので、可変で借用できません
--> borrow_thrice.rs:6:19
|
4 | let r1 = &s;
| - immutable borrow occurs here # 不変として借用しているのに
5 | let r2 = &s;
6 | let r3 = &mut s;
| ^ mutable borrow occurs here # 可変として借用しています
7 | }
| - immutable borrow ends here
理由: #2 と同様。
このスクラップは2024/01/01にクローズされました