本文へスキップ
BecomeCoder

Rustコース · 第5章 参照と借用 · レッスン20

可変参照 ― &mut で書き換える

ブラウザで完結

導入

借りた値を変更したいこともあります。たとえば文字列に追記する関数。そのときは「変更可能な参照」——可変参照 &mut を使います。ただし、ここには Rust の安全性を支える重要な制約が付きます。

説明

fn main() {
    let mut s = String::from("hello");   // 変更するので mut が必要

    add_world(&mut s);                    // 可変参照で貸す

    println!("{s}");                      // hello, world
}

fn add_world(text: &mut String) {         // &mut String = 可変で借りる
    text.push_str(", world");
}
  • 貸す側の slet mut s でなければなりません(元が変更可能でないと、可変で貸せない)。
  • &mut s … 「可変参照」を作って貸します。関数側は text: &mut String で受け取り、中身を書き換えられます。
  • text.push_str(...)s の中身が実際に変わります。所有権はムーブしていないので、mains はそのまま使え、変更も反映されています。

ここで Rust の借用のルールの1つ目が登場します。

同じ値に対する可変参照は、同時に1つまで。

fn main() {
    let mut s = String::from("hello");

    let r1 = &mut s;
    let r2 = &mut s;      // ← エラー! 同時に2つの可変参照は作れない

    println!("{r1} {r2}");
}

なぜこんな制約が? これが次のレッスンの主題「データ競合の防止」です。「同時に複数の場所から書き換えられる」状態をそもそも作れないようにすることで、Rust はある種のバグを根絶しています。1つずつ使うなら(スコープが重ならなければ)何度でも可変参照を作れます。

試すには

上のエラーは、r1 を使い終えてから r2 を作る(2つの可変参照のスコープが重ならない)ようにすれば解決します。「可変参照は同時に1つだけ」という制約が、次で説明するデータ競合をどう防ぐのかを見ていきましょう。

実際に動かしてみよう

下のエディタにRustを書いて「実行」を押すと、学習用シミュレータが println! の出力を表示します(本物のrustcではなく、教材の範囲を再現した軽量エンジンです)。struct・enum・match・トレイト・Vec/String/HashMap・Option/Result なども動きます。本文の例を書き換えて動かしてみましょう(所有権・借用チェッカーのコンパイルエラーは再現しないため、動きの確認用として使ってください)。

Rust — ブラウザ内で実行(学習用シミュレータ)

Rustの教材サブセットを動かす学習用シミュレータを読み込みます(本物のrustcではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。