Rustの参照と借用(&)の正しい使い方

先生

Rustの参照と借用をマスターして、メモリ安全なコードを書こう!

Rustの参照と借用とは?基本概念をわかりやすく解説

Rustにおける参照と借用は、メモリ安全性を確保するための重要な概念です。所有権システムと密接に関連しており、これらの理解なしにRustプログラミングは難しいと言えるでしょう。この記事では、参照と借用について初心者にもわかりやすく解説します。

Rustは、ガベージコレクション(GC)に頼らずにメモリ安全性を実現する言語です。そのため、メモリの管理はプログラマの責任となりますが、所有権システムがコンパイル時にメモリに関する問題を検出してくれます。

所有権、借用、参照という3つの概念を理解することで、Rustのメモリ管理の仕組みを理解できます。

所有権とは、あるメモリ領域に対して、一つの変数だけが所有権を持つというルールです。所有者がスコープから外れると、メモリは自動的に解放されます。

借用とは、所有権を持たない変数(参照)が、所有権を持つ変数から一時的にメモリ領域を借りることを指します。借用には、可変の借用と不変の借用があります。

参照とは、別の変数が所有するデータへのアクセスを提供するものです。参照は、所有権を移動させることなくデータを利用できます。

これらの概念を理解することで、Rustのコンパイラがどのようにメモリ安全性を保証しているのかが見えてきます。

不変の参照(&)の使い方:読み取り専用アクセス

不変の参照(&)は、データを読み取るだけで変更しない場合に利用します。複数の不変の参照は同時に存在できます。

例えば、以下のようなコードは有効です。

fn main() {
    let s = String::from("hello");
    let r1 = &s;
    let r2 = &s;
    println!("{}, {}", r1, r2);
}

この例では、sというString型の変数に対して、r1r2という2つの不変の参照を作成しています。どちらの参照もsの値を読み取るだけで、変更は行いません。

不変の参照は、データの安全性を確保する上で重要な役割を果たします。

可変の参照(&mut)の使い方:変更可能なアクセス

可変の参照(&mut)は、データを変更する場合に利用します。ただし、可変の参照は同時に一つしか存在できません。

以下に例を示します。

fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    r1.push_str(", world!");
    println!("{}", r1);
}

この例では、sを可変として定義し、r1という可変の参照を作成しています。r1を通じて、sの内容を変更しています。

重要なのは、可変の参照と不変の参照は同時に存在できないという点です。これは、データの競合状態を防ぐためのRustの仕組みです。

// これはコンパイルエラーになります
// fn main() {
//     let mut s = String::from("hello");
//     let r1 = &mut s;
//     let r2 = &s;
//     println!("{}, {}", r1, r2);
// }

上記のコードはコンパイルエラーになります。可変の参照r1が存在する間は、不変の参照r2を作成することはできません。

ダングリング参照:参照が無効になるケース

ダングリング参照とは、参照しているメモリ領域がすでに解放されている状態を指します。Rustのコンパイラは、ダングリング参照が発生する可能性のあるコードをコンパイル時に検出し、エラーを発生させます。

以下はダングリング参照の例です。

// これはコンパイルエラーになります
// fn main() {
//     let reference_to_nothing = dangle();
// }
//
// fn dangle() -> &String {
//     let s = String::from("hello");
//     &s // sはdangleの最後にドロップされるため、参照は無効
// }

この例では、関数dangle内で作成されたsへの参照を返そうとしていますが、sは関数dangleのスコープを抜ける際に解放されるため、返される参照は無効になります。Rustのコンパイラはこのエラーを検出し、コンパイルを阻止します。

Rustの借用チェッカーは、ダングリング参照を未然に防ぐための強力なツールです。

参考リンク

まとめ

Rustの参照と借用は、メモリ安全性を確保するための重要な仕組みです。不変の参照(&)と可変の参照(&mut)の区別、そして借用規則を理解することで、安全で効率的なRustプログラムを書くことができます。所有権と借用の概念をマスターし、Rustコンパイラの力を最大限に活用しましょう。