🦉

【Rust】Railsユーザーが雰囲気で理解した"所有権"

2024/06/17に公開

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では、s1s2の両方が存在し続けるのとは対照的です。

例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()
}

この例では、&s1s1を不変借用しています。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 ssを可変借用しています。change関数はsの内容を変更できますが、借用中に他の不変借用や可変借用を作ることはできません。Railsでは、オブジェクトの変更が自由に行えます。

3. 所有権のルールとデータ競合の防止

Rustの所有権システムは、データ競合やメモリの解放ミスを防ぐために設計されています。例えば、可変借用が同時に1つしかできないルールにより、同時に複数の箇所でデータを変更することによる競合を防ぎます。

まとめ

Rustの所有権システムは、メモリ管理とデータの安全性を保証するために非常に強力な仕組みです。Railsのガベージコレクションと異なり、Rustでは所有権と借用のルールに従うことで、コンパイル時にメモリ管理の問題を防止します。

Discussion