導入
借りた値を変更したいこともあります。たとえば文字列に追記する関数。そのときは「変更可能な参照」——可変参照 &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");
}
- 貸す側の
sはlet mut sでなければなりません(元が変更可能でないと、可変で貸せない)。 &mut s… 「可変参照」を作って貸します。関数側はtext: &mut Stringで受け取り、中身を書き換えられます。text.push_str(...)でsの中身が実際に変わります。所有権はムーブしていないので、mainのsはそのまま使え、変更も反映されています。
ここで 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つだけ」という制約が、次で説明するデータ競合をどう防ぐのかを見ていきましょう。