この記事は
なんかよくわからないなーと思っていた時に良いISSUEを見つけたので、備忘録としてまとめるものである。
cf: borrow/ref: Not clear what's the difference between ref and & · Issue #390 · rust-lang/rust-by-example
"&"とは
公式?だとここあたり
参照のこと。リソースの所有権を借用することを意味する。
基本的に借用というコンテキストで語られることには"&"を利用する模様。
"ref"とは
公式?のここによると
借用というよりも構造体やタプルのメンバーをデストラクトすることを想定している模様。
"ref"と"&"で束縛してみる
fn main() {
let x = 123;
let x_ref_1 = &x;
let ref x_ref_2 = &x;
let &x_ref_3 = x;
let ref x_ref_4 = x;
assert_eq!(x, *x_ref_1); // x_ref_1 == &x なのでOK
assert_eq!(x, *x_ref_2); // x_ref_2 == &&x なのでエラー
assert_eq!(x, *x_ref_3); // &x_ref_3 と x での束縛がmissmatch typeエラー
assert_eq!(x, *x_ref_4); // x_ref_4 == &x なのでOK
}
syntaxとしては、"&"は"*"と同様な扱い。
一方、"ref"は"mut"とかと同様な扱いといった感じ。
基本的に参照による束縛を行う時に使うが、"&"は右辺、"ref"は左辺で参照であることを示すときにそれぞれ用いる感じっぽい。
"ref"と"&"でデストラクトしてみる
fn main() {
let x = 3;
let s1 = Some(&x);
assert_eq!(s1.unwrap(), &x);
let s2 = Some(x);
assert_eq!(s2.unwrap(), x);
match s1 {
Some(y) => assert_eq!(y, &x),
None => {},
}
match s1 {
Some(&y) => assert_eq!(y, x),
None => {},
}
match s1 {
Some(ref y) => assert_eq!(y, &&x),
None => {},
}
match s2 {
Some(y) => assert_eq!(y, x),
None => {},
}
/* エラー
match s2 {
Some(&y) => assert_eq!(y, &x),
None => {},
}*/
match s2 {
Some(ref y) => assert_eq!(y, &x),
None => {},
}
}
match Option(&x) { Some(&y) => assert_eq!(y, x), ... }
なるほどそりゃそうだ感ある。
結論
左辺にref、右辺に&とでも覚えておけばよい感。
今の所、refが完全に要らない子なんだが。。
所有権持ってる状態で、借用を起こさずに参照を取るためには"ref"を使うのかな。
もうちょっと書いてたら腹落ちしそう。