Rustのオーナーシップ　その2

# References and Borrowing

これは以下の記事を翻訳して、自分なりに整理した物です。

https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html

以下の様にすると、タプル型でStging型の参照を返す必要がなくなる。

```rs
fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}
```

これはString型の変数ではなく、String型の参照を渡している。

![](https://doc.rust-lang.org/book/img/trpl04-05.svg)

```rs
    let s1 = String::from("hello");

    let len = calculate_length(&s1);
```

&s1を使用すると、s1の値を参照するが、それを所有しない参照を作成できる。
所有していないので、範囲外になってもドロップしない。

```rs
fn calculate_length(s: &String) -> usize { // s is a reference to a String
    s.len()
}
```

同様に、関数のパラメータは&を使用して、引数の型が参照型である事を表す。
所有権がないため、スコープを外れても所有権を返す必要が無い。

参照を関数パラメータの借用という。
借り物なので、終わったら返さなければならない。
借りている物を変更することも出来ない。

```rs
fn main() {
    let s = String::from("hello");

    change(&s);
}

fn change(some_string: &String) {
    some_string.push_str(", world");
}
```

![コメント 2020-08-31 075601.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624329/ca9fe88e-f09f-dae3-8f90-8f2b39ef0c60.jpeg)

変数がデフォルトで不変であるように、参照も同様です。参照しているものを変更することはできない。

## Mutable References

上のコードをエラーが出ないように修正。

```rs
fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}
```

sをmutに変更する必要がある。次に、&mutを使用して可変参照を作成する。

しかし、可変可能な参照には大きな制約がある。
特定のスコープ内の特定のデータへの変更可能な参照は1つだけ。
以下はエラーになる。

```rs
fn main() {
    let mut s = String::from("hello");

    let r1 = &mut s;
    let r2 = &mut s;

    println!("{}, {}", r1, r2);
}
```

![コメント 2020-08-31 080321.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624329/d8228cc4-4512-562d-5ec9-189bbd700e16.jpeg)

この制約のメリットはコンパイル時にデータ競合を防ぐことが出来る。
データの競合は以下の時に発生する。

* 二つ以上のポインターが同じデータに同時にアクセスする。
* 少なくとも一つのポインターがデータの書き込みに使用されている。
* データへのアクセスを同期するメカニズムがない。

データの競合は想定外の動作を引き起こし、診断と修正が困難になる。
Rustはデータの競合のあるコードもコンパイル出来ないため、この問題の発生を防ぐ。
以下の様にして同時参照ではなく、複数の可変参照を可能にする。

```rs
    let mut s = String::from("hello");

    {
        let r1 = &mut s;
    } // r1 goes out of scope here, so we can make a new reference with no problems.

    let r2 = &mut s;
```

変更可能な参照と不変の参照を組み合わせるための同様のルールがある。
以下はエラーになる。

```rs
    let mut s = String::from("hello");

    let r1 = &s; // no problem
    let r2 = &s; // no problem
    let r3 = &mut s; // BIG PROBLEM

    println!("{}, {}, and {}", r1, r2, r3);
```

![コメント 2020-08-31 081122.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624329/eba8840b-f9e7-8077-606c-e3a0f87f2911.jpeg)

不変の参照がある間は可変な参照を持つことは出来ない。
ただし、複数の不変参照は、読み込みだけのため、問題は無い。

参照のスコープは、それが導入されたところから始まり、その参照が最後に使用されたときまで続くことに注意。
たとえば、不変参照の最後の使用は、可変参照が導入される前に発生するため、このコードはコンパイルされる。

```rs
let mut s = String::from("hello");

    let r1 = &s; // no problem
    let r2 = &s; // no problem
    println!("{} and {}", r1, r2);
    // r1 and r2 are no longer used after this point

    let r3 = &mut s; // no problem
    println!("{}", r3);
```

r1とr2の参照はprintln!で終了する。可変参照r3が作成される前なので、スコープは重複されないため、コンパイルが可能。

## Dangling References

```rs
fn main() {
    let reference_to_nothing = dangle();
}

fn dangle() -> &String {
    let s = String::from("hello");

    &s
}
```

これはエラーになります。

![](https://taki-lab.site/bocci/wp-content/uploads/2020/08/3aea6a5d218959154928ff3931a56167.jpg)

sはdangle内に作成されるため、dangleのコードが終了すると、sは割り当て解除される。
しかし、上のコードではそれの参照を返そうとしたためエラーとなる。
ここでの解決策は、文字列を直接返すこと。

```rs
fn no_dangle() -> String {
    let s = String::from("hello");

    s
}
```

## The Rules of References

* いつでも、1つの変更可能な参照または任意の数の不変の参照を持つことができます。
* 参照は常に有効でなければなりません。

次に、別の種類の参照であるスライスについて見ていきます。