blog.dopana

Back

Rust基礎シリーズの第6回です。所有権によってメモリ安全性が保証されますが、すべての場所で値を移動させるとコードが複雑になります。「借用(Borrowing)」を使うと、所有権を奪うことなくデータにアクセスできます。

参照による借用#

参照を使うと、所有権を取得せずに値を参照できます。参照は & 演算子を使用して作成します。

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

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("'{s1}' の長さは {len} です。");
}
rust

calculate_length は参照 &String を受け取るため、s1 は移動せず借用されます。関数呼び出し後も s1 は有効なままです。

可変参照#

デフォルトでは、参照は不変です。借用したデータを変更するには、可変参照 &mut を使用します。

fn change(s: &mut String) {
    s.push_str(", world");
}

fn main() {
    let mut s = String::from("hello");
    change(&mut s);
    println!("{s}");
}
rust

可変参照を作成するには、元の変数も mut で宣言されている必要があります。

借用の根本ルール#

Rustはコンパイル時にデータ競合を防ぐため、以下の厳格なルールを適用します。

ある時点で存在できるのは、任意の数の不変参照 (&T) または 単一の可変参照 (&mut T) のどちらか一方のみです。両方を同時に持つことはできません。

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

let r1 = &s; // OK
let r2 = &s; // OK
// let r3 = &mut s; // エラー: 不変参照が存在するため可変参照は作成できません
println!("{r1} と {r2}");
rust

この「エイリアスまたは可変性のどちらか一方のみ」というルールにより、プログラムの他の部分が読み取り中にデータが予期せず変更されるのを防ぎます。

スライス#

スライスは、コレクション全体ではなく、連続した要素のシーケンスへの参照です。

文字列スライス#

文字列スライス (&str) は String の一部を参照します。

let s = String::from("hello world");

let hello: &str = &s[0..5];
let world: &str = &s[6..11];
rust

文字列リテラル ("hello") は、コンパイルされたバイナリデータへの文字列スライスです。

配列のスライス#

スライスは配列やベクターに対しても使用できます。

let a = [1, 2, 3, 4, 5];
let slice: &[i32] = &a[1..3];

assert_eq!(slice, &[2, 3]);
rust

まとめ#

参照(& および &mut)による借用により、データを安全に共有できます。スライス(&str および &[T])は、シーケンスへの柔軟な参照ビューを提供します。シリーズの次回テーマは「構造体(Struct)」です。

参考資料#