参照と借用

参照

所有権を移動せずに値を参照することができます。 借用には不変参照(&T)と可変参照(&mut T)があります。

不変参照(&T)

値を変更できない参照です。複数の不変参照を同時に持つことができます。

#![allow(unused)]
fn main() {
let s = String::from("hello");
let r1 = &s; // 不変参照
let r2 = &s; // 不変参照
println!("{} and {}", r1, r2); // 出力: hello and hello
}

可変参照(&mut T

値を変更できる参照です。 ただし、可変参照は一度に一つしか持つことができません。

#![allow(unused)]
fn main() {
let mut s = String::from("hello");
let r1 = &mut s; // 可変参照
r1.push_str(", world");
println!("{}", r1); // 出力: hello, world
println!("{}", s); // 出力: hello, world
}

借用

関数の引数に参照を取ることを借用と呼びます。

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

    let len = calculate_length(&s1);

    // '{}'の長さは、{}です
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

借用のルール

  1. 不変参照と可変参照を同時に持つことはできない

    同じスコープ内で不変参照と可変参照を同時に持つことはできません。これにより、データ競合を防ぎます。

    #![allow(unused)]
    fn main() {
    let mut s = String::from("hello");
    let r1 = &s; // 不変参照
    let r2 = &mut s; // エラー: 不変参照が存在する間は可変参照を持てない
    }
  2. 可変参照は一度に一つだけ

    可変参照は一度に一つしか持つことができません。これにより、データの一貫性を保ちます。

    #![allow(unused)]
    fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s; // 可変参照
    let r2 = &mut s; // エラー: 可変参照は一度に一つだけ
    }
  3. 可変参照は一度に一つだけ

    借用はそのスコープ内でのみ有効です。スコープを抜けると借用は無効になります。

    let r;
    {
        let s = String::from("hello");
        r = &s; // エラー: sのスコープを抜けるとrは無効になる
        println!("{}", r)
    }
    println!("{}", r) // エラー: スコープを抜けたためrは無効

借用の利点

  • メモリ安全性: 借用により、所有権を移動せずにデータを安全に操作できます。
  • 効率性: 借用を使用することで、不要なデータのコピーを避け、効率的にメモリを使用できます。