今年の言語はRust その５


# 今年の言語はRust その５

Rustを学びます

勉強ページは日本語ドキュメント

[プログラミング言語Rust](https://doc.rust-jp.rs/)

Rustの日本語ドキュメント 2nd Edition
https://doc.rust-jp.rs/book/second-edition/

オリジナル
https://doc.rust-lang.org/book/



## 4. 所有権を理解する

やっとRustっぽい雰囲気がでてきました

「以下のルールを肝に免じておいてください」

> 1. Rustの各値は、所有者と呼ばれる変数と対応している。
> 2. いかなる時も所有者は一つである。
> 3. 所有者がスコープから外れたら、値は破棄される。

ぽかんだな

```rust
fn main(){

    {
        // 文字列リテラル
        let mut s = "hello";
        //   可変 できない
        //   |
        // 4 |         let mut s = "hello";
        //   |             ----^
        //   |             |
        //   |             help: remove this `mut`
        //   |
        //   = note: #[warn(unused_mut)] on by default
    }

    {
        // String型は可変化できる
        let mut s = String::from("hello");
        s.push_str(", world!");
        
        println!("{}", s);
    }
}

```

二つの違いは、

・　文字列リテラルは、コンパイル時に中身が判明しているので、テキストはバイナリファイルに直接ハードコードされる。高速で高効率。
・ String型は、可変かつ伸長可能なテキストをサポートするために、実行時にヒープ領域を確保する。

### 変数とデータの相互作用法：ムーブ


```rust
let x = 5;
let y = x;
// 整数はスタックに積まれる

let s1 = String::from("hello");
let s2 = s1;
// ヒープに確保される

```

それでは、ヒープに確保されたString型の再代入はどうなる？？
つまり、解放のタイミングが議論になる
なんとRustでは再代入されると、先の変数は不要とされ、コンパイラに解放される！

```rust
fn main(){

    // コピーではなくて、ムーブ！
    let s1 = String::from("hello");
    let s2 = s1; // <= s1は破棄される.
    
    println!("{}, world!", s1);
}

error[E0382]: borrow of moved value: `s1`
 --> src/main.rs:6:28
  |
4 |     let s2 = s1;
  |              -- value moved here  <= ムーブされてるよ！
5 |     
6 |     println!("{}, world!", s1);
  |                            ^^ value borrowed here after move
  |
  = note: move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait

```


ここでの学びは

## 「Rustでは、自動的にデータの"deep copy"が行われることは絶対にない」

### クローン

スタック上のデータだけでなくて、ヒープデータのdeep copyはcloneしよう

```rust

let s1 = String::from("hello");
let s2 = s1.clone();

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


==
s1 = hello, s2 = hello

```


Stringの使い方には注意が必要!!

関数に渡すと、渡された関数のスコープに入り、じ


```rust
fn main(){

	// ヒープのムーブ
    let s = String::from("hello");
    
    takes_ownership(s);
    // println!("{}", s); <- 解放されている
    
    
    // スタックのコピー
    let x = 5;
    
    makes_copy(x);
    
    println!("{}", x);
}


fn takes_ownership(some_string: String){
    println!("{}", some_string);
}

fn makes_copy(some_integer: i32){
    println!("{}", some_integer);
}
```

### 戻り値とスコープ

```rust
fn main(){

    let s1 = gives_ownership();
    
    let s2 = String::from("hello");
    
    let s3 = takes_and_gives_back(s2);
    
    println!("{}", s1);
    println!("{}", s2); // Error! s2はすでにmoveされている
    println!("{}", s3);
    
    
    
}


fn gives_ownership() -> String{

    let some_string = String:: from("hello");
    
    some_string // <- 呼び出し元に「ムーブ」

}

fn takes_and_gives_back(a_string: String) -> String{
    
    a_string // <- 呼び出し元にムーブ
    
}
```

ただ、これだと、変数を関数に渡すたびに所有権が移ってしまい
変数も毎回返却して大変だよね

```rust
fn main(){

    let s1 = String::from("hello");
    
    let (s2, len) = calculate_length(s1);
    
    println!("The length of '{}' is {}.", s2, len);
    println!("{}.", s1); // <- s1はムーブされている
}

fn calculate_length(s: String) -> (String, usize){
    
    let length = s.len();
    
    (s, length)
}
```

大丈夫！
Rustには「参照」が準備されているよ！
次回！


イエス！