1. 為什麼需要借用
昨天學到:一個變數的值被移動 (move) 後,原變數就不能再用。
fn main() {
let s1 = String::from("hello");
let s2 = s1; // move
println!("{}", s2);
// println!("{}", s1); // s1 已經失效
}
這在實務上會很不方便,有時候我們只是想讀取變數的值,而不是拿走它。這時候就要用「借用」。
2. 不可變參考 (Immutable Reference)
不可變參考讓我們可以讀取資料,但不取得所有權。
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()
}
輸出:
The length of 'hello' is 5
s1 傳入函數後依然有效,因為只是「借用」,沒有被移走。
3. 可變參考 (Mutable Reference)
如果要修改變數內容,可以用 &mut 建立可變參考。
fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}", s);
}
fn change(s: &mut String) {
s.push_str(", world");
}
輸出:
hello, world
在同一個作用域中,Rust 保證同一時間只能有一個可變參考,否則會報錯。不可變參考則可以同時存在多個。
4. 可變參考的限制範例
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s; // 編譯錯誤,不能同時有兩個可變參考
println!("{}, {}", r1, r2);
}
這樣寫會報錯。原因是如果兩個地方同時能改變同一份資料,會導致不可預期的結果。Rust 在編譯期就禁止這種情況。
5. 不可變 + 可變參考的混用
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
// let r3 = &mut s; // 與不可變參考同時存在
println!("{}, {}", r1, r2);
}
不可變參考和可變參考不能同時存在,必須分時段使用。
6. 學習心得與補充
今天學到的借用讓我覺得很新鮮。昨天才覺得所有權會讓變數很快失效,結果今天就看到解法:只要用「參考」就能把值借出去,又不會失去原本的變數。這讓我聯想到前幾天的變數不可變性和 mut,因為在借用的時候,Rust 也區分了不可變參考和可變參考,就像一開始學到的變數是否能被改的概念在這裡又延伸了一次。相比之下,我覺得 Rust 的 & 很直觀,Rust 的 & 用法很直觀,讓我一眼就能知道自己到底是要「讀取」還是「修改」。雖然限制有點多,像同一時間不能有兩個可變參考,但其實想一想,這樣可以避免同時修改資料時產生混亂。這些規則把前幾天學到的知識串了起來,讓我更能理解 Rust 為什麼要這樣設計。