Open6
所有権
Rustのメモリ管理の話で所有権とは登場する。
既存のプログラミング言語は下記2つの方法でメモリ管理をおこなってきた。
- プログラマがコード内で明示的にメモリ解放を宣言する(C言語のfree)
- 定期的に使用されていないメモリを検索して解放するガベージコレクション(java,python)
Rustはこのメモリ管理(どのタイミングでメモリを解放するか?)について、第三の選択肢を採用している。
- | - |
---|---|
誰が | コンパイラが |
何を | メモリを |
なぜ | GCより動作を早くかつプログラマが明示的に行うよりも安全に |
どう | 所有権システムを使って |
する | 解放する |
所有権規則
- Rustの各値は、所有者と呼ばれる変数と対応している
- いかなる時も所有者は一つである
- 所有者がスコープから外れたら、値は破棄される
String型
- ユーザー入力を受け付けて保持したい場合に便利
- ヒープにメモリを確保するので、コンパイル時にサイズが不明なテキストも保持できる
- &strと違って可変。なぜかというとコンパイル時に不明な量のメモリをヒープに確保して内容を保持する。
つまりは、メモリは実行時にOSに要求される、String型の使用が終わったらOSにこのメモリを返還しなければならい。
Stack領域に値を積んでいくような型は、デフォルトでコピートレイトが実装されてる。
対して、ヒープ領域にメモリ空間を確保して変数を束縛するような値は(ex. String型、Box型、Vec型など)はコピーのコストが高くなるので明示的に .clone()メソッドを呼び出さない限りはムーブ処理になり所有権が移動する。
以上から、ムーブ処理が起こるのはコピーコストが高くなるヒープ領域に変数を束縛するような型のみになる。スタック領域に束縛される型は所有権の移動が発生せずデフォルトでコピートレイトが実装されている。
所有権と関数
関数に値を渡すことと、値を変数に代入することは近い。ようするに、関数に変数を渡すと所有権のムーブやコピーが行われる。
参照と借用
関数に所有権をムーブしてしまった時は、関数側のスコープを抜けた段階で、Drop(メモリの解放)してしまうため、関数呼び出し元で束縛していた変数は無効になってしまう。もし、呼び出し元のスコープでも変数の所有権をムーブさせずに有効なままにしておきたい場合は、関数の引数には変数の参照を渡すことにする。
この関数の引数に参照を取ることを借用と呼びます。
参照の規則
- 任意のタイミングで、一つの可変参照か不変な参照いくつでものどちらかを行える。
- 参照は常に有効でなければならない。
ここでいう有効とは束縛されている変数、つまり所有権を持っている変数がドロップされていないことを(スコープ内にいること)という理解で良さそう。