[Rust]所有権、所有権、所有けんけんけけんけん

`Rust`が良い、`Rust`が良いと一部のエンジニアから聞いていたのですが、どうせ文法的には`Golang`と`Scala`の中間くらいでしょう、くらいに考えていましたが、今は反省しています。大きなパラダイム・シフトがありました。

> 所有権

この概念が`Rust`の中でも大きく理解を難解にさせていると思います。しかし一方でこの概念は今までのプログラミングで実行時に問題になってきた内容を前倒してコンパイル時に解決する、という解決策を`Rust`は提供しているのです。

まずは普通の実行っぷりを書いてみます

```src/main.rs
fn main() {
    let s = vec!["udon".to_string(),"ramen".to_string(),"soba".to_string()];
    let t = s;
    let u = t;
    println!("u[0] is: {}", u[0]);
}
```
```bash:実行結果

$ cargo run
   Compiling hello v0.1.0 
    Finished dev [unoptimized + debuginfo] target(s) in 0.47s
     Running `target/debug/hello`
u[0] is: udon

```

そしてこちらが所有権のエラーが発生するパターンです。コンパイルエラーになっています。

```src/main.rs
fn main() {
    let s = vec!["udon".to_string(),"ramen".to_string(),"soba".to_string()];
    let t = s;
    let u = s;
    println!("u[0] is: {}", u[0]);
}
```
```bash:実行結果

$ cargo run
   Compiling hello v0.1.0 
warning: unused variable: `t`
 --> src/main.rs:3:9
  |
3 |     let t = s;
  |         ^ help: consider using `_t` instead
  |
  = note: #[warn(unused_variables)] on by default

error[E0382]: use of moved value: `s`
 --> src/main.rs:4:9
  |
3 |     let t = s;
  |         - value moved here
4 |     let u = s;
  |         ^ value used here after move
  |
  = note: move occurs because `s` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
error: Could not compile `hello`.

To learn more, run the command again with --verbose.

```

`Rust`では通常の代入処理時に値の所有権の移動を行います。上の例ではs -> t -> uと代入処理を行っており、その順で所有権が移動、最終的にuにアクセスして要素を表示するものになっています。対して下の例では、s -> t, s -> uと代入を行っております。最初、s -> tと所有権が移動したタイミングでsは値にアクセスする権限を持っていません。そのため、代入処理ができないため、エラーが発生するのです。

`Rust`のすごいところはこれをコンパイラが解決しているところです。

もちろん代入処理だけでなく、所有権を失った変数にアクセスしようものならコンパイルエラーが発生します

```src/main.rs
fn main() {
    let s = vec!["udon".to_string(),"ramen".to_string(),"soba".to_string()];
    let t = s; // sはここで所有権を失う
    let u = t;
    println!("s[0] is: {}", s[0]); // 所有権のないsにアクセス！
}

```

```bash:実行結果
$ cargo run
   Compiling hello v0.1.0 
warning: unused variable: `u`
 --> src/main.rs:4:9
  |
4 |     let u = t;
  |         ^ help: consider using `_u` instead
  |
  = note: #[warn(unused_variables)] on by default

error[E0382]: use of moved value: `s`
 --> src/main.rs:5:29
  |
3 |     let t = s;
  |         - value moved here
4 |     let u = t;
5 |     println!("s[0] is: {}", s[0]);
  |                             ^ value used here after move
  |
  = note: move occurs because `s` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
error: Could not compile `hello`.

To learn more, run the command again with --verbose.
```

大切なことなのでもう一度いいます。これをコンパイル時に`Rust`は解決しています。
上記のコードを`C++`で書くと下記のようなコードになります。

```c++:main.cpp
#include <stdio.h>
#include <string>
#include <iostream>
#include <vector>

int main(){
    auto s = new std::vector<std::string>();s->push_back("udon");s->push_back("ramen");s->push_back("soba");
    auto t = s; s = NULL;
    auto u = s; s = NULL; 
    std::cout << (*s)[0] << std::endl;
    return 0;
}
```

でコンパイルできてしまいます。

```bash:実行結果
$ g++ -std=c++11 main.cpp 
$ ./a.out 
Segmentation fault: 11

```

実行時エラーになってしまうわけです。大規模になればなるほど、バグを探すのがめんどくさいあれです。
NULLを代入しなければもちろんアクセスできますが、メモリ解放の難解さを内包したままになるので`Rust`に寄せて記述しています。
この機能を持つプログラミング言語は今の所`Rust`くらいしかないのではないでしょうか。

ほら大規模開発を`Rust`でしたくなってきたでしょう？とはいえ、まだライブラリが貧弱なので一筋縄にはいかないでしょうけども。