1& で参照を作る — 貸すだけで渡さない
& を付けて参照 r を作っても所有権は city に残ったまま、という借用の最小の例です。代入なら moved になっていた場面で、参照なら両方の名前から同じ値を読めます。「貸すだけで、持ち主は変わらない」というイメージをこの3行でつかんでください。
fn main() {
let city = String::from("Tokyo");
let r = &city; // 所有権は移さず「貸す」だけ
println!("参照から読む: {}", r);
println!("持ち主からも読める: {}", city);
}
2関数には & を付けて貸し出す
引数を &String で受ける関数に &greeting を渡せば、呼び出し後も greeting を使い続けられる、という前レッスンのムーブ問題の解決編です。同じ値を2回渡せている点に注目してください。「読むだけの関数には参照で渡す」は、実務 Rust でもっとも基本的な習慣です。
fn show(message: &String) {
println!("表示: {}", message);
}
fn main() {
let greeting = String::from("おはようございます");
show(&greeting); // & を付けて貸し出す
show(&greeting); // 所有権は手元にあるので何度でも渡せる
println!("greeting = {}", greeting);
}
3借用した値から計算結果だけを返す
参照で借りた String の長さを調べ、usize の結果だけを返す関数の例です。値は借りるだけ、返すのは計算結果、という「読み取り専用ヘルパー関数」の典型形です。バリデーションや集計など、データを変更しない処理はすべてこの形で書けます。
fn byte_count(s: &String) -> usize {
s.len() // 借りた値を読むだけ
}
fn main() {
let title = String::from("Rust入門");
let len = byte_count(&title);
println!("タイトル: {}", title);
println!("バイト数: {}", len);
}
4読み取り専用の参照は同時に複数作れる
同じ String への参照 r1 と r2 を同時に作って両方から読む例です。誰も書き換えない読み取り専用の共有なら、何人に貸しても矛盾が起きないためコンパイラも許可します。「読むだけなら何個でも」というこのルールは、次のレッスンの可変参照の制限と対になっています。
fn main() {
let data = String::from("共有データ");
let r1 = &data;
let r2 = &data; // 読み取り専用の参照は同時に複数OK
println!("r1 = {}, r2 = {}", r1, r2);
// & の参照経由で書き換えることはできない(読み取り専用)
println!("持ち主: {}", data);
}
5入力チェックの関数群に同じ値を貸し回す
ユーザー名のバリデーションを「空でないか」「長すぎないか」という小さな関数に分け、同じ input を参照で順に貸して回す実務寄りの例です。どの関数も借りるだけなので、チェックが何段あっても input の所有権は手元に残り続けます。Web アプリの入力検証やフォーム処理は、まさにこの構造で書きます。
fn is_empty_name(name: &String) -> bool {
name.len() == 0
}
fn is_too_long(name: &String) -> bool {
name.len() > 12
}
fn main() {
let input = String::from("Alice");
// 同じ input を借用で複数の関数に貸し回してチェックする
if is_empty_name(&input) {
println!("名前が空です");
} else if is_too_long(&input) {
println!("名前が長すぎます");
} else {
println!("OK: {}", input);
}
}