■ はじめに
https://dk521123.hatenablog.com/entry/2023/04/22/234808
の続き。 今回は、Rust 特有の考え方の「所有権 (ownership)」について 纏めてみた。
目次
【0】プログラムのメモリ管理方法 1)明示的にメモリ確保・解放する 2)ガベージコレクション 3)所有権 (ownership) 【2】所有権の三大原則 【3】保有権の利点 補足:Rustにおけるスタック領域 / ヒープ領域 【4】所有権に関わる用語 1)束縛(Binding) / 再束縛(Rebinding) 2)参照(Reference) / 借用 (borrow)
【1】プログラムのメモリ管理方法
1)明示的にメモリ確保・解放する 2)ガベージコレクション 3)所有権 (ownership) ★今回のテーマ★
1)明示的にメモリ確保・解放する
* プログラマが自分で、明示的にメモリ確保・解放する * e.g. C言語
2)ガベージコレクション
* 定期的に使用されていないメモリを検索し で使用されなくなったら自動的に破棄 * e.g Java, C#
3)所有権 (ownership)
* 今回のテーマ
https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html
【2】所有権の三大原則
1)値には「所有権」がある 2)所有権は移動(move) 可能だが、いかなる時も「所有者」は一つ 3)「所有者」がスコープから外れたら、値は破棄
スコープ例
fn main() { { let num = 123; } // スコープ外れるのでnumは破棄 println!("number is {}", num); // 破棄されてるんでコンパイルエラー }
【3】保有権の利点
* 所有権を持つ変数が関数などのスコープから外れるときに、 メモリが解放され、値が破棄される => ヒープ上に確保された値がどこで解放されるかを コンパイル時に決定できるようになる => ガーベジコレクションのような仕組みを使用せずに メモリ解放が自動的される
補足:Rustにおけるスタック領域 / ヒープ領域
スタック領域
* 『固定長』のデータを格納する際に使用 => コンパイルする時点で、データサイズが分かる
ヒープ領域
* 『可変長』のデータを格納する際に使用 => コンパイルする時点では、データサイズは(厳密には)分からない => 例:String型で何文字格納されるかコンパイル時点では分からないケースがある
【4】所有権に関わる用語
1)束縛(Binding) / 再束縛(Rebinding)
fn main() { // let で、変数を束縛する (bind) let x = 1; print!("result = {x}\n"); // let で、変数を再束縛する (rebind) let x = 2; print!("result = {x}\n"); }
2)参照(Reference) / 借用 (borrow)
fn main() { let name: String = String::from("Mike"); // 関数に渡す変数を &name のように参照(Reference)で渡すと // 所有権は渡さないので破棄されない let reult = say_hello(&name); //let reult = say_hello(name); // nameの所有権が奪われる(コンパイルエラー) println!("{}, {}", name, reult); // 関数の後でもヒープ領域変数(name)が使用 } //fn say_hello(name: String) -> String { fn say_hello(name: &String) -> String { // 借用 (borrow)で、所有権を移動させずにその値を参照 format!("Hello, {}!", name) }
参考文献
https://maku77.github.io/p/4nx8hqy/
https://isub.co.jp/rust/rust-ownership/
https://zenn.dev/ucwork/articles/cfe579cbf5647e
関連記事
Rust ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/04/22/234808