メインコンテンツにスキップ
モジュール 3 · レッスン 2 / 2コース内の 6/14~15 min
モジュールのレッスン (2/2)

参考文献と借用

Rust では、所有権を関数に受け渡したり渡したりするのは面倒な場合があります。これを解決するために、Rust は 参照 (&) を使用します。

値への参照を作成することは、借用と呼ばれます。

不変参照

参照は、型または変数の前に & シンボルを付けることによって宣言されます。デフォルトでは、参照は不変です。値の読み取りは可能ですが、変更はできません。

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

    // We pass a reference to s1, not ownership
    let len = calculate_length(&s1);

    // s1 is still usable here!
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize { // s is a reference to a String
    s.len()
} // Here, s goes out of scope, but since it doesn't own the value, nothing happens

変更可能な参照

借用した値を変更する必要がある場合は、&mut で 可変参照 を使用する必要があります。元の変数も mut で可変として宣言する必要があります。

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

    // We pass a mutable reference
    change(&mut s);

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

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

借入のルール

コンパイル時のメモリ破損とデータ競合を防ぐために、Rust は 2 つの基本的なルールを強制します。

  1. 同時に値に対する不変参照 (&T) をいくつでも持つことができます。
  2. または、値への変更可能な参照 (&mut T) を一度に 1 つだけ持つことができます。

同じスコープ内の同じ値に対する不変参照と可変参照を混在させることは絶対にできません。

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

let r1 = &s; // Valid
let r2 = &s; // Valid
// let r3 = &mut s; // COMPILATION ERROR! You cannot create &mut s if s is already borrowed as immutable

参照範囲と非語彙有効期間 (NLL)

歴史的に、参照のスコープは、それが作成されたブロックの終わりまで続きました。現在、Rust のコンパイラは Non-Lexical Lifetimes (NLL) のおかげでよりスマートになっています。参照のスコープは、ブロックの最後ではなく、実際に使用される最後の行で終了します。

これにより、次のコードは完全に有効になります。

Rust
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2); // Last use of r1 and r2. The immutable references expire here!

let r3 = &mut s; // Valid! No active immutable references exist at this point

自分で試してみてください

運動#rust.m3.l2.e1
試行回数: 0読み込み中…

& 記号を使用して、s1 の不変参照を Calculate_length 関数に渡します。

エディターを読み込み中…
ヒントを表示

`/* TODO \_/`を`&s1`に置き換えて、文字列への不変の参照を渡します。

3 回の試行後に解決策が利用可能になります

運動#rust.m3.l2.e2
試行回数: 0読み込み中…

変数 s を変更可能にし (let mut s)、変更関数に変更可能参照 (&mut s) を渡して、文字列を変更できるようにします。

エディターを読み込み中…
ヒントを表示

「let s」の代わりに「let mut s」を使用し、「change(&mut s);」を呼び出します。

3 回の試行後に解決策が利用可能になります

運動#rust.m3.l2.e3
試行回数: 0読み込み中…

Declare a variable s containing String::from("Rust"). Create two distinct immutable references r1 and r2 to s, and finally print both references separated by a space using the println! macro.

エディターを読み込み中…
ヒントを表示

Assign `let r1 = &s;` and `let r2 = &s;` to obtain two immutable references, then print them with `println!("{} {}", r1, r2);`.

3 回の試行後に解決策が利用可能になります