今天來看 Rust 最獨特和最重要的特性之一:所有權系統-ownership。這個系統是 Rust 實現記憶體安全和並行安全的基礎,也是區別於其他語言的關鍵特性。
Rust 的所有權系統遵循三個基本規則:
在 Rust 中,變數的作用域是一個重要概念:
{ // s 在這裡無效,它尚未聲明
let s = "hello"; // 從這裡開始,s 是有效的
// 使用 s
} // 此作用域已結束,s 不再有效
Rust 使用移動(move)語義來管理heap上的資料:
let s1 = String::from("hello");
let s2 = s1; // s1 被移動到 s2,s1 不再有效
// println!("{}", s1); // 這行會導致編譯錯誤
如果我們確實需要深度複製heap上的資料,可以使用 clone
方法:
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2); // 這行正常工作
對於存儲在stack上的簡單類型,Rust 使用複製語義:
let x = 5;
let y = x; // x 被複製到 y,兩者都有效
println!("x = {}, y = {}", x, y); // 正常工作
函數參數和返回值也涉及所有權轉移:
fn main() {
let s = String::from("hello");
takes_ownership(s); // s 的值移動到函數裡
// println!("{}", s); // 這行會報錯,s 已經無效
let x = 5;
makes_copy(x); // x 的值被複製到函數裡
println!("{}", x); // 這行正常工作
}
fn takes_ownership(some_string: String) {
println!("{}", some_string);
}
fn makes_copy(some_integer: i32) {
println!("{}", some_integer);
}
函數返回值也可以轉移所有權:
fn main() {
let s1 = gives_ownership();
let s2 = String::from("hello");
let s3 = takes_and_gives_back(s2);
}
fn gives_ownership() -> String {
let some_string = String::from("yours");
some_string
}
fn takes_and_gives_back(a_string: String) -> String {
a_string
}
為了避免所有權轉移帶來的不便,Rust 提供了引用(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()
}
這裡 &s1
創建了一個指向 s1
的引用,但並不擁有它。這個過程被稱為借用(borrowing)。
如果我們想要修改借用的值,可以使用可變引用:
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
注意:在特定作用域中,對於某個特定數據,要麼只能有一個可變引用,要麼可以有任意多個不可變引用。
Rust 編譯器確保引用永遠不會變成懸垂引用:
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String { // 錯誤:返回的引用指向一個無效數據
let s = String::from("hello");
&s
} // s 在這裡離開作用域並被丟棄
切片(Slice)是對集合中部分連續元素的引用:
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];
字符串字面值就是切片:
let s: &str = "Hello, world!";
明天,我們再來討論Rust生命週期概念,這是與所有權系統緊密相關的另一個重要 Rust 特性。