Rust言語のOwnership、Scope

#Rustとは
A language empowering everyone
to build reliable and efficient software.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/853ac02d-2adf-2952-4f3d-00096d81fefc.png)

出典：https://www.rust-lang.org/

Rust言語は、ガベージコレクションがないコンパイル型の言語であり、
厳しいチェックあるコンパイル段階でバグを減らすことでよりよい品質の製品を作ることは可能です。

#Most Loved Languages
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/d9c67567-f9f7-d405-f293-b3b37687a076.png)

出典：https://insights.stackoverflow.com/survey/2019#most-loved-dreaded-and-wanted
一位です。今後ももっと人気な言語になりますかね。

#Ownershipとは
Rustの変数はOwner（持ち主）が存在する特性です。

Ownership特性はRustの言語ではとても重要な特性です。
JAVAなどの言語では、データの記憶場所はStackか、Heapかはあまり気にしないでよいですが、
Rustなどのシステム向けの言語では十分注意する必要があります。
・Stack（First In　Last Out）:固定長のデータは保存可能（整数、ポインターのアドレスなど）。アクセス早い
・Heap：サイズ不定、変更する可能性があるデータなど。アクセス比較的に遅い

# Ownership Rules
- Each value in Rust has a variable that’s called its owner. 
- There can only be one owner at a time.
- When the owner goes out of scope, the value will be dropped.

#Variable Scope
```rust
fn main() {
    println!("=======start");
    {                      // ここはs変数はまだ定義していないため、sは使えない
        let s = "hello";   // sは有効です

        println!("sは{}です。", s); //sは有効なので、使えます
    }                      // スコープ終了なので、sは使えない
    println!("=======end");
}
```

{}でスコープで区別します。

##数字などStack-Only Data: Copyのデータなら、別の変数に付与してもよい
```rust
fn main() {
  let x = 5;
  let y = x;
  println!("xは{}です。", x);
  println!("yは{}です。", y);
}
```

結果：
>xは5です。
>yは5です。

Stack-Only Data: Copy

- All the integer types, such as u32.
- The Boolean type, bool, with values true and false.
- All the floating point types, such as f64.
- The character type, char.
- Tuples, if they only contain types that are also Copy. For example, (i32, i32) is Copy, but (i32, String) is not.

##文字列の場合、別の変数に付与すると、元変数は使えなくなる。
```rust
fn main() {
  let s1 = String::from("hello");
  let s2 = s1;  //s1のOwnerがなくなるので、dropされる。s1のスコープは終了。
  println!("s1は{}です。", s1);
  println!("s2は{}です。", s2;
}
```
結果：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/7fe2b857-c2d4-9f67-5b94-1e9cfc77a11f.png)

Javaなどの言語ではこの動作になりません。

##文字列でもエラーにしたくない場合は、cloneメソッドで使える
下記のサンプルは問題ありません。

```rust
let s1 = String::from("hello");
let s2 = s1.clone();  //heapからデータをコピー

println!("s1 = {}, s2 = {}", s1, s2);
```

結果：
>s1 = hello, s2 = hello

#Ownershipと関数
##正常例
```rust
fn main() {
    let s1 = String::from("hello world");

    let (s2, len) = calculate_length(s1);

    println!("文字列 '{}' の長さは {}です。", s2, len);

}

fn calculate_length(s: String) -> (String, usize) {
    let length = s.len(); //文字列の長さ

    (s, length)  //「;」がないコードは戻り値です。
}
```

結果：
>文字列 'hello world' の長さは 11です。

パラメータの変数s1は使っていないため、正常でした。

##異常例
```rust
fn main() {
    let s1 = String::from("hello world");

    let (s2, len) = calculate_length(s1);

    println!("文字列 '{}' の長さは {}です。", s2, len);

    println!("元文字列は '{}' です。", s1); //s1はdropされたので、「value borrowed here after move」エラーです。
}
```
##関数で渡してもエラーにしたくない場合は、mutでポインターを渡す
```rust
fn main() {
    let mut s1 = String::from("hello world");

    let len = calculate_length(&mut s1);

    println!("元文字列は '{}' です。長さは{}です。", s1, len);
}

fn calculate_length(s: &String) -> usize {
    let length = s.len(); //文字列の長さ

    length //「;」がないコードは戻り値です。
}
```
結果：
>元文字列は 'hello world' です。長さは11です。

#参照のルール(The Rules of References)

- At any given time, you can have either one mutable reference or any number of immutable references.(可変参照は一つしない OR　不変参照は任意個)
- References must always be valid.（参照は常に有効である。owerがある状態）

##エラー例
```rust
fn main() {
    let reference_to_nothing = dangle();
}

fn dangle() -> &String {
    let s = String::from("hello");
    &s // sのポインターを戻りますが、sの実体はなくなったので、エラーになる。
}
```

Ownershipとは：https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html
参照ロール：https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references

以上