iT邦幫忙

2025 iThome 鐵人賽

DAY 4
0
Rust

Rust 後端入門系列 第 4

Day 4 Rust 所有權與借用

  • 分享至 

  • xImage
  •  

今天我們將要介紹 Rust 最核心的關鍵:所有權系統, Rust 並沒有垃圾回收(Garbage Collection),通常情況下會導致記憶體洩露,但是 Rust 的所有權系統讓記憶體洩露的發生率降到極低。


所有權 (Ownership)

Rust 的所有權有三個重點

  • 每個值都有一個擁有者
  • 同一時間只能有一個擁有者
  • 離開作用域後,資料將失效

有點抽象,很難理解?我們搭配所有權轉移的介紹,希望大家能夠更直接理解所有權的概念。

所有權轉移

何時會發生所有權轉移?

  • 賦值給另一個變數

    fn main() {
        let s1 = String::from("Hello");
        let s2 = s1; // s1 的所有權轉移到 s2,s1 失去所有權
    
        // println!("{}", s1); // 拿到註解後,將發生編譯錯誤!因為 s1 已失去資料所有權
        println!("{}", s2); // 將顯示 Hello 
    }
    
    
  • 傳遞參數給函數

    fn take_ownership(s: String) {
        println!("{}", s); // 顯示 Hello 
    } // s 離開作用域後,資料將失效
    
    fn main() {
        let s1 = String::from("Hello");
        take_ownership(s1); // s1 傳遞給函數參數,所有權已被轉移
    
        // println!("{}", s1); // s1 已失去資料所有權,去除註解後,將發生編譯錯誤
    }
    
    
  • 從函數回傳值

    fn create_string() -> String {
        let s = String::from("Hello");
        s // 從函數返回值,所有權將轉移
    }
    
    fn main() {
        let s1 = create_string(); // 接收回傳的值,並取得所有權
        println!("{}", s1); // 顯示 Hello 
    }
    

借用 (Borrowing) 與引用 (&)

有些時候我們只是想要使用數值,但是不想轉移所有權時,就需要借用和引用。

不可變借用

不想轉移擁有權,只是想借用資料來讀取時,就需要採用不可變借用的方式。

範例:

fn calculate_length(s: &String) -> usize {
    s.len() // 可以讀取,但不能修改
}

fn main() {
    let s1 = String::from("Hello");
    let len = calculate_length(&s1); // 借用 s1, s1 不會失去所有權

    println!("'{}'的長度是 {}", s1, len); // 正常輸出 s1 的內容
}

可變借用

我們想要修改借用的數值時,就需要加上 mut ,來完成可變借用。

範例:

fn change_string(s: &mut String) {
    s.push_str(", World!");
}

fn main() {
    let mut s = String::from("Hello");
    change_string(&mut s); // 可變借用

    println!("{}", s); // 輸出:Hello, World!
}

借用時需要特別注意,多個不可變借用可以同時存在,但是當宣告可變借用後,先前的不可變借用將失效。

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

    // 多個不可變借用可以同時存在
    let s1 = &s;
    let s2 = &s;
    println!("{}", s1);
    println!("{}", s2);

    // 可變借用,先前的不可變借用將失效
    let s3 = &mut s;
    s3.push_str(" World");
    // println!("{}", s1); // 編譯錯誤,因為 s1 已經失效

    let s4 = &s;
    println!("{}", s4); // 正常,顯示 Hello World
}



上一篇
Day 3 Rust 基礎語法(2): 函數、結構體與模組
系列文
Rust 後端入門4
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言