【Rust】Railsユーザーが雰囲気で理解した"所有権"
1. 所有権とは何か
Railsでは、メモリ管理はガベージコレクションにより自動的に行われます。開発者はメモリ管理についてあまり考えなくても良いです。一方、Rustでは所有権システムというメモリ管理の仕組みがあり、プログラムの安全性とパフォーマンスを保証します。
基本的な違い
- Rails (Ruby): メモリ管理はガベージコレクターが自動で行う。
- Rust: 所有権システムに基づき、プログラムがメモリの管理を自動で行うが、開発者は所有権のルールを守る必要がある。
2. Rustの所有権システム
Rustの所有権システムの基本ルールは次のとおりです:
- 各値には所有者が1つだけ存在する
- 所有者がスコープを抜けると、その値は破棄される
- 借用は不変借用と可変借用があり、不変借用は複数同時に可能だが、可変借用は1つだけ
例1: 所有権の移動(Move)
Rubyではオブジェクトのコピーは簡単ですが、Rustでは所有権が移動します。
fn main() {
let s1 = String::from("hello");
let s2 = s1; // 所有権がs1からs2に移動
println!("{}", s2); // "hello"
// println!("{}", s1); // エラー: s1はもう有効でない
}
この例では、s1
の所有権がs2
に移動します。s1
は無効になり、もう使えません。Railsでは、s1
とs2
の両方が存在し続けるのとは対照的です。
例2: 不変借用(Immutable Borrowing)
不変借用を使って、変数の値を一時的に借用できます。借用中も元の変数は有効です。
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1); // 不変借用
println!("The length of '{}' is {}.", s1, len); // s1はまだ有効
}
fn calculate_length(s: &String) -> usize {
s.len()
}
この例では、&s1
でs1
を不変借用しています。calculate_length
関数はs1
を変更できません。Railsでは、オブジェクトを関数に渡しても、そのオブジェクトを変更することが可能です。
例3: 可変借用(Mutable Borrowing)
可変借用を使って、変数の値を変更できます。ただし、可変借用は1つだけしか作成できません。
fn main() {
let mut s = String::from("hello");
change(&mut s); // 可変借用
println!("{}", s); // "hello, world"
}
fn change(s: &mut String) {
s.push_str(", world");
}
この例では、&mut s
でs
を可変借用しています。change
関数はs
の内容を変更できますが、借用中に他の不変借用や可変借用を作ることはできません。Railsでは、オブジェクトの変更が自由に行えます。
3. 所有権のルールとデータ競合の防止
Rustの所有権システムは、データ競合やメモリの解放ミスを防ぐために設計されています。例えば、可変借用が同時に1つしかできないルールにより、同時に複数の箇所でデータを変更することによる競合を防ぎます。
まとめ
Rustの所有権システムは、メモリ管理とデータの安全性を保証するために非常に強力な仕組みです。Railsのガベージコレクションと異なり、Rustでは所有権と借用のルールに従うことで、コンパイル時にメモリ管理の問題を防止します。
Discussion