Rustacean（ラステイシャン）になりたい。3: 参照と借用

# 前回の所有権のムーブ（所有権の移動）について復習
前回に所有権（所有者）機能について話をしました。
その中で所有権のムーブ（所有権に移動）について話をしました。

その時のサンプルでは、「print_string(s);」を実行すると`s`の値の所有権がprint_stringにムーブされるので
以降で`s`を参照するとコンパイルエラーになりました。

```rust
fn main() {
    let s = String::from("value");

    // sの値の所有権がprint_stringにムーブされる。
    print_string(s);

    // ここで「value borrowed here after move」コンパイルエラーになる。
    println!("{}", s);
}

fn print_string(s: String) {
    println!("{}", s);
}
```

この所有権のムーブはメモリを安全に使用する為の重要な機能ですが、関数に渡した以降その変数が使用できないのは非常に不便です。
この不便さを改善するのが、「参照」という機能です。

# 参照とは変数のリンクのようなもの
参照を例えるなら何が適切なのだろうと悩みましたが、「変数のリンクのようなもと」と例えることにしました。
### 参照とは
- 参照は、値そのものは持たない
- 値を持たない代わりに参照元の変数のリンク情報（ポインタ）を持っている
- 値は参照元の変数の値を使用する
- **所有権のムーブはしない。**
![{36451DD2-0627-4FBB-A5DF-E844678B5D39}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/43e88710-7d15-3a4f-4687-ec5b3bec4221.png)

### エクセルでイメージ化してみた
完全ではありませんが、エクセルのセルを使って参照をイメージ化してみました。
![{8CA82B12-DAC8-4477-A8CA-09DA793B77C0}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/2ce395a3-a247-d6bf-7f07-644b4c30e755.png)

- A2セルには実値「value」を入力
- **B2はA2の参照として「=A2」を入力**
- C2はB2の値が"value"の場合"●"を表示、そうでなければ"○"を表示する

**このB2セルがRustの「参照」のイメージになります。**

# 借用
「参照」ではない変数の場合、関数の引数に値を渡すと「所有権のムーブ」されますが、
「参照」の場合、関数の引数に値を渡すと**「貸与」**されます。
そして貸与された値を受け取って使うことを**「借用」**といいます。
:warning: マニアリュには「貸与」というキーワードは出てきません。私が個人的に表現しているだけです。

```rust
fn main() {
    let s1 = String::from("value");
    let ref_s1 = &s1;

    // ref_s1を「貸与」する
    printString(ref_s1);
}

fn printString(s: &String) {
    //値がs変数として「借用」する
    print!("{}", s);
}
```
| 借用 | 貸与 |
| --- | --- |
| printStringのs | ref_s1 |

あえてコンパイルエラーにしてエラーメッセージを確認すると
「参照」を変数に代入することも「借用」となるようです。
![{914C6CBA-7379-48C0-9541-9E0971753514}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/3e4f6b1e-889c-a7ab-5e47-8927822a44e3.png)

```console
let ref_s1 = &s1;
             --- `s1` is borrowed here
```
と、4行目の代入文が「\`s1\` is borrowed here」となっています。

| 貸与 | 借用 |
| --- | --- |
| &s1 | ref_s1 |

# 不変変数の参照

## 宣言
型に「&」を付けて宣言します。

```rust:宣言の例
let ref_s1: &String;
```
この例では文字列型（String）の「参照」変数を宣言しています。

## 代入
不変変数の「参照」変数への代入の例です。
```rust:代入の例
let s1 = String::from("value");
let ref_s1: &String;

// 代入
ref_s1 = &s1;
```
このように参照元（代入元）にも「&」を付けて代入します。

宣言と代入を１行で記述することも可能です。
この場合は、ref_s1変数の型は「&String」に推論してくれるので明示的に型指定をする必要はありません。
```rust:宣言（型は推論）＋代入の例
let s1 = String::from("value");

// 宣言（型は推論）＋代入
let ref_s1 = &s1;
```
![{0B3AD703-0C08-44F3-9B00-08472866F2A6}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/0a4aa82b-c338-1051-d642-30332ac1deb8.png)

## 所有権のムーブがされていないことを検証

### 代入した場合
「s1」を「ref_s1」に代入した後にs1を使用しても「value borrowed here after move」コンパイルエラーにならないことが確認できます。
```rust
let s1 = String::from("value");
let ref_s1 = &s1;

// コンパイルエラーにならない
print!("{}", s1);
```

### 関数の引数に渡した場合
「s1」を「printString」の引数に使用しても「value borrowed here after move」コンパイルエラーにならないことが確認できます。
```rust
fn main() {
    let s1: String = String::from("value");

    // s1の参照を引数に渡す
    printString(&s1);
    
    // コンパイルエラーにならない
    print!("{}", s1);
}

fn printString(s: &String) {
    print!("{}", s);
}
```

## 参照変数の使用
では、参照変数を使ってみます。
上で書いたエクセルイメージに真似て変数をセル名にしてみました。
![{AE0078FD-1B1B-44C2-B02E-D31896D27136}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/fa694f0c-f805-9612-c8b9-baea893d9e2e.png)


```rust
let A2 = String::from("value");
let B2 = &A2;

// C2
if B2 == "value" {
    print!("●");        
} else {
    print!("○");        
}
```
このprint!の結果は「●」となります。

## 不変変数の「参照」変数は複数宣言することが可能
不変変数の「参照」変数は複数宣言することが可能です。
```rust
let s1 = String::from("value");

// 不変変数の参照変数は複数宣言することが可能
let ref_s1_1 = &s1;
let ref_s1_2 = &s1;

// 出力： value value value
print!("{} {} {}", s1, ref_s1_1, ref_S1_2);
```

# 可変変数の参照
可変変数の参照は2種類の参照が作成できます。

- 共有参照（Shared references）： 値の変更が出来ない参照
- 可変参照（Mutable references）： 値の変更が出来る参照

:warning: 不変変数の参照は「共有参照」と明示的に表現しませんでしたが、不変変数の参照は共有参照となります。

可変変数の参照は、いくつかの制限があるので注意が必要です。

##  共有参照（Shared references）
### 宣言
不変変数の「参照」変数と同じです。
```rust:宣言の例
let ref_s1: &String;
```

### 代入
不変変数の「参照」変数への代入と同じです。
```rust:代入の例
// 可変変数の宣言
let mut s1 = String::from("value");

// 「共有参照」変数宣言
let ref_s1_1: &String;

// 参照を代入
ref_s1_1 = &s1;

// 宣言（型は推論）＋代入の例
let ref_s1_2 = &s1;
```
変数宣言と代入を1行で書いた例です。
```rust:代入の例
// 宣言（型は推論）＋代入の例
let ref_s1_1 = &s1;
```


### 可変変数の「共有参照」変数は複数宣言することが可能
可変変数の「共有参照」変数は複数宣言することが可能です。
見るだけの参照ならいくつでもいいよ。ってことです。

```rust
let mut s1 = String::from("value");

// 「共有参照」変数は複数宣言することが可能
let ref_s1_1 = &s1;
let ref_s1_2 = &s1;
        
// 出力: value value value 
print!("{} {} {}", s1, ref_s1_1, ref_s1_2);

```

## 可変参照
可変変数では、データを変更できる「可変参照」変数を宣言出来ます。

### 宣言
参照型は型に「&mut」を付けて宣言します。
```rust:宣言の例
let mref_s1: &mut String;
```

### 代入
参照元にも「&mut」を付けて代入します。
```rust:代入の例
// 可変変数の宣言
let mut s1 = String::from("value");

// 「可変参照」変数の宣言
let mref_s1: &mut String;

// 代入
mref_s1 = &mut s1;
```

変数宣言と代入を1行で書いた例です。
```rust:代入の例
// 宣言（型は推論）＋代入の例
let mref_s1 = &mut s1;
```

### 可変変数の「共有参照」と「可変参照」の変数を同時にスコープ内で宣言することは出来ない
「共有参照」使用中に「可変参照」の変数は宣言できません。

```rust
let mut s1 = String::from("value");

let ref_s1 = &s1;

// コンパイルエラー「cannot borrow `s1` as mutable because it is also borrowed as immutable」になる。
let mref_s1 = &mut s1;

print!("{} {}", ref_s1, mref_s1);
```

![{055F242B-7688-47F9-954F-9733B2F07FDC}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/ccd9ae45-ed3d-e60c-d9a8-82624dc7d1d7.png)

なぜこの宣言が許されないか。:thinking:

下記サンプルを使って説明すると、
変更不可としてref_s1変数を宣言しているのに、「do_some_ting(&mut &s1);」を実行すると
do_some_ting関数内でs1の値が更新されるかもしれません。するとref_s1は変更不可にもかかわらず参照元のs1の値が変更されてしまいます。これではref_s1の「不変」という保証が崩れてしまいます。
これでは、もしref_s1が不変あることを前提に実装していると不具合を発生させてしまいます。
```rust
let mut s1 = String::from("value");

let ref_s1 = &s1;

// これが許されると、この関数内でs1の値が更新されてしまう。
do_some_thing(&mut &s1);

print!("{} {}", ref_s1, mref_s1);
```

### 可変変数の「可変参照」変数はスコープ内で複数宣言することが出来ない
スコープ内では「可変参照」の借用は1つだけです。これは「変更できるのは一つだけ」ということです。

```rust
let mut s1 = String::from("value");

let mref_s1_1 = &mut s1;

// コンパイルエラー「cannot borrow `s1` as mutable more than once at a time」になる
let mref_s1_2 = &mut s1;
```
![{5DE03A3F-C15B-4DBC-B7FF-9F6B9CAB2D05}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/0012c2c3-aa5a-67d7-5075-bc1b42a53e2a.png)

子スコープ内も出来ません。
```rust
let mut s1 = String::from("value");

let mref_s1_1 = &mut s1;

// 子スコープ
{
    // コンパイルエラー「cannot borrow `s1` as mutable more than once at a time」になる
    let mref_s1_2 = &mut s1;
    println!("{}", mref_s1_2);
}

println!("{}", mref_s1_1);

```
![{3903788A-15C4-4F2F-A19D-CE2A83B42876}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/ccaa907d-3954-2798-b240-a021425ac96f.png)

関数の引数に渡す時も出来ません。
```rust
fn main() {
    let mut s1 = String::from("value");
   
    let mref_s1 = &mut s1;
    
     // コンパイルエラー「cannot borrow `s1` as mutable more than once at a time」になる
    printString(&mut s1);

    println!("{}", mref_s1);
}

fn printString(s: &mut String) {
    print!("{}", s);
}
```
![{7320F588-883E-47DA-B3D9-7B4160135716}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3477554/3c3790d1-e843-5569-1d8e-33e8ec8442a0.png)

関数の引数に渡す時は、可変参照変数を宣言している場合は、その変数を渡します。
```rust
let mut s1 = String::from("value");

let mref_s1 = &mut s1;

// mref_s1を渡す
printString(mref_s1);

println!("{}", mref_s1);
```

### 参照中は再代入は出来ない
可変参照、共有参照ともに参照中は参照元変数を再代入することは出来ません。
他で参照しているに別のものにしてはダメということです。
```rust
let mut s1 = String::from("value");

// 借用
let ref_s1 = &s1;

// 再代入
// コンパイルエラー「cannot assign to `s1` because it is borrowed」になる
s1 = String::from("value_2"); 

println!("{}", ref_s1);
```

### まとめ
参照を柔軟に使用するなら
参照を変数に代入して使用するのではなく、直接関数に借用させたほうがよさそうです。（個人的感想）
```rust
fn main() {
    let mut s1 = String::from("value");

    // 変数定義しないで直接借用
    print_string(&s1);

    s1 = String::from("value_2"); 

    // 変数定義しないで直接借用
    do_some_thing(&mut s1);
    do_some_thing(&mut s1);

    // 変数定義しないで直接借用
    print_string(&s1);
}

fn print_string(s: &String) {
    print!("{}", s);
}

fn do_some_thing(s: &mut String) {
    print!("{}", s);
}

```

### 参照変数に代入して借用させるケースってなんだろう？？？ 
### その1：変更処理をブロックさせたい時
このサンプルのように、ref_s1を宣言してからprint_stringまでの間に変更する処理はエラーになります。
print_stringまでの間は値が変更されないことが保証されます。
```rust
fn main() {
    let mut s1 = String::from("value");

    // ここからs1変数は変更不可
    let ref_s1 = &s1;

    // エラーになる
    // do_some_thing(&mut s1);

    // ここに到達するまでs1(ref_s1)が変更されないことが保証される
    print_string(ref_s1);

    // これ以降にref_s1を使用していなので、ここからはs1は変更可能 
    do_some_ting(&mut s1);
}

fn print_string(s: &String) {
    print!("{}", s);
}

fn do_some_thing(s: &mut String) {
    print!("{}", s);
}
```

### その2　別のもに上書きするのをブロックする時
このサンプルのようにs1を「氏名」の値を格納する変数として宣言した後に、まったく別の「住所」の値で上書きされないような時。
```rust
fn main() {
    let mut s1 = String::from("氏名");

    let m_ref_s1 = &mut s1;

    // エラーになる　s1を別のもにさせない
    //s1 = String::from("住所"); 

    m_ref_s1.push_str("様");

    println!("{m_ref_s1}");

}
```