44
26

More than 5 years have passed since last update.

Rustの"&"と"ref"の違い

Last updated at Posted at 2018-02-25

この記事は

なんかよくわからないなーと思っていた時に良い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"を使うのかな。
もうちょっと書いてたら腹落ちしそう。

44
26
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
44
26