Chuyển đến nội dung chính
Mô-đun 3 · Bài học 2 trong tổng số 26/14 trong khóa học~15 min
Bài học theo mô-đun (2/2)

Tài liệu tham khảo và mượn

Trong Rust, việc chuyển quyền sở hữu qua lại cho các chức năng có thể rất tẻ nhạt. Để giải quyết vấn đề này, Rust sử dụng tham chiếu (&).

Việc tạo tham chiếu đến một giá trị được gọi là Mượn.

Tài liệu tham khảo bất biến

Một tham chiếu được khai báo bằng cách thêm ký hiệu & vào tiền tố loại hoặc biến. Theo mặc định, các tham chiếu không thể thay đổi: chúng cho phép đọc giá trị nhưng không sửa đổi nó.

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

Tài liệu tham khảo có thể thay đổi

Nếu cần sửa đổi giá trị mượn, bạn phải sử dụng tham chiếu có thể thay đổi với &mut. Biến ban đầu cũng phải được khai báo có thể thay đổi bằng 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");
}

Quy tắc vay

Để ngăn chặn tình trạng hỏng bộ nhớ và chạy đua dữ liệu tại thời điểm biên dịch, Rust thực thi hai quy tắc cơ bản:

  1. Bạn có thể có bất kỳ số lượng tham chiếu bất biến (&T) nào cho một giá trị cùng một lúc.
  2. HOẶC bạn có thể có chính xác một tham chiếu có thể thay đổi (&mut T) cho một giá trị tại một thời điểm.

Bạn tuyệt đối không thể kết hợp các tham chiếu bất biến và có thể thay đổi cho cùng một giá trị trong cùng một phạm vi:

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

Phạm vi tham chiếu và thời gian tồn tại phi từ vựng (NLL)

Về mặt lịch sử, phạm vi của một tham chiếu kéo dài cho đến hết khối mà nó được tạo. Ngày nay, trình biên dịch của Rust thông minh hơn nhờ Thời gian sống không từ vựng (NLL): phạm vi của tham chiếu kết thúc ở dòng cuối cùng mà nó thực sự được sử dụng, không nhất thiết phải ở cuối khối.

Điều này làm cho đoạn mã sau hoàn toàn hợp lệ:

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

Hãy tự mình thử

tập thể dục#rust.m3.l2.e1
Nỗ lực: 0Đang tải…

Truyền tham chiếu bất biến của s1 cho hàm Calculate_length bằng ký hiệu &.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Thay thế `/* TODO \_/`bằng`&s1` để chuyển một tham chiếu bất biến tới chuỗi.

Giải pháp khả dụng sau 3 lần thử

tập thể dục#rust.m3.l2.e2
Nỗ lực: 0Đang tải…

Làm cho biến s có thể thay đổi (let mut s) và chuyển một tham chiếu có thể thay đổi (&mut s) cho hàm thay đổi để cho phép nó sửa đổi chuỗi.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

Sử dụng `let mut s`thay vì`let s`và call`change(&mut s);`.

Giải pháp khả dụng sau 3 lần thử

tập thể dục#rust.m3.l2.e3
Nỗ lực: 0Đang tải…

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.

Đang tải trình chỉnh sửa…
Hiển thị gợi ý

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

Giải pháp khả dụng sau 3 lần thử