所有権はむずい
今までノリでコンパイラが指示するように参照&
をつけたりしていた節があったが、学び直しました。
結局は公式ドキュメントですね。
学んだポイント
-
&mut T
は変更可能な参照(そのままだけど、、) -
&mut T
は2つ同時に設定できない。
解釈:変更可能な参照が競合できない。 - immutableな参照とmutableな参照は共存できない。(それもそう)
&T
と&mut T
が別の変数に与えられてはいけない。
2つ目の具体例(↑リンク見ていただければよいのですが、、)
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
エラー内容
$ cargo run
Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0499]: cannot borrow `s` as mutable more than once at a time
(エラー: 一度に`s`を可変として2回以上借用することはできません)
--> src/main.rs:5:14
|
4 | let r1 = &mut s;
| ------ first mutable borrow occurs here
| (最初の可変な参照はここ)
5 | let r2 = &mut s;
| ^^^^^^ second mutable borrow occurs here
| (二つ目の可変な参照はここ)
6 |
7 | println!("{}, {}", r1, r2);
| -- first borrow later used here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0499`.
error: could not compile `ownership`
3つ目の具体例
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
(エラー: `s`は不変で借用されているので、可変で借用できません)
--> borrow_thrice.rs:6:19
|
4 | let r1 = &s; // no problem
| - immutable borrow occurs here
5 | let r2 = &s; // no problem
6 | let r3 = &mut s; // BIG PROBLEM
| ^ mutable borrow occurs here
7 | }
| - immutable borrow ends here
しっかりと向き合って考えてみるとそりゃそうって言う話なのですが、
ちゃんと、仕組みを頭で整理することでちゃんと中身を把握して使えそうな気がしています。
あとはポイントはダングリング参照ができないってところですね。
実際にコードを書いていく中でそんなにダングリング参照を引き起こしそうなケースってないのかなと感覚的には思いましたがコンパイラの気持ちを理解するのに役立ったかなと思っています。