iT邦幫忙

0

二、三天學一點點 Rust:來! References and Borrowing(24)

  • 分享至 

  • xImage
  •  

🦀 懸垂參考 (Dangling References)

懸垂參考的危險性:
使用懸垂參考是非常危險的,因為它指向的記憶體可能已經被其他資料覆寫,或者已經不再有效。嘗試存取懸垂參考會導致不可預測的行為,例如程式崩潰、讀取到錯誤的資料,甚至可能引發安全漏洞。

fn main() {
    let result = area();
}

fn area() -> &String {
    let city = String::from("New York");
    &city
}
  1. fn area() -> &String
    這個函式的簽名表明它會回傳一個指向 String 的參考 (&String)。

  2. let city = String::from("New York");
    在 area 函式內部,這一行建立了一個新的 String 物件,其內容是 "New York"。這個 String 物件被儲存在堆疊 (stack) 上,並且它的所有權屬於變數 city。

  3. &city
    這一行創建了一個指向 city 變數的 String 的參考,並試圖將這個參考回傳。

懸垂參考的產生:
問題在於 city 變數是在 area 函式內部宣告的。當 area 函式執行完畢後,city 變數會離開其作用域 (scope),並且它所擁有的 String 物件所佔用的記憶體會被釋放 (dropped)。
然而,area 函式卻試圖回傳一個指向這個已經被釋放的記憶體的參考。在 main 函式中,result 變數會接收到這個指向無效記憶體的參考。這個 result 就變成了一個懸垂參考 (dangling reference)。

fn main() {
    let result = area();
    println!("{}", result);
}

fn area() -> String {
    String::from("New York")
}

我們將程式碼修正後,可以發現,area 函式的簽名表明它會直接回傳一個 String 的所有權,而不是回傳一個指向在函式結束後就會被釋放的局部變數的參考,也避免了懸垂參考的出現。

🧩 陣列與元組中的擁有權(Ownership with Arrays and Tuples)

在 Rust 中,所有權(ownership)不僅適用於單一變數,也適用於資料集合,如陣列(array)元組(tuple)。接著我們就來看看,資料在陣列與元組中的存放方式、是否會觸發擁有權移轉,以及如何安全地存取元素,基本上來說,前面的擁有權了解之後,這邊的概念也是一樣的。


✅ 範例一:陣列中的基本型別(Copy)

fn main() {
    let registrations = [true, false, true];
    let first = registrations[0];
    println!("{:?} and {:?}", registrations, first);
}

🔍 說明:

  • registrations 是布林值陣列,屬於 Copy 型別
  • 使用 let first = registrations[0] 時,值被複製,不會轉移所有權。
  • registrationsfirst 都可以正常使用。

❗ 範例二:陣列中的堆積資料型別(非 Copy)

fn main() {
    let languages = [String::from("Rust"), String::from("Java")];
    let first = &languages[0];
    println!("{:?} and {:?}", languages, first);
}

🔍 說明:

  • languagesString 陣列,String非 Copy 型別(擁有堆積資料)
  • 若寫成 let first = languages[0]; 將會觸發所有權移轉,導致 languages 之後無法使用。
  • 使用 let first = &languages[0]; 可以 借用(borrow) 資料,避免所有權被移轉。
  • ✅ 此方式安全可行,兩者都可使用。

🔸 範例三:元組中的所有權行為

fn main() {
    let tuple = ("Roger", 21, "human");
    let first = tuple.0;
    println!("{:?} and {}", tuple, first);
}

🔍 說明:

  • tuple 中是 &'static stri32,這些都是 Copy 型別或靜態借用型別
  • tuple.0 是 Copy,所以 tuple 本身仍然可以使用。
  • tuple 中包含 String 或其他堆積型別,則存取後會影響擁有權。

📘 所有權行為比較

資料型別 是否 Copy 取出元素是否移轉所有權 解法建議
bool, i32 ✅ 是 ❌ 否 直接取用即可
String, Vec ❌ 否 ✅ 是(除非用借用) 使用 &array[i]
&str ✅ 是 ❌ 否 可安心使用

✅ 小結

  • 在 Rust 中,陣列與元組的元素若為 Copy 型別,取用不會影響所有權。
  • 若為非 Copy 型別(如 String),直接取出元素會導致所有權轉移。
  • 使用參照(&T)能安全地借用資料,避免所有權問題。
  • 正確認識資料型別特性,有助於避免常見的編譯錯誤與記憶體問題。

📚 參考文件:


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言