iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
Rust

Rust 30 天養成計畫:從零到 CLI 專案系列 第 6

Day 6:所有權 (Ownership)

  • 分享至 

  • xImage
  •  

Rust 為了避免記憶體錯誤,引入所有權 (ownership) 系統。

Rust 的所有權有三大規則:

  • 每個值 (value) 在任一時間點只能有一個擁有者 (owner)。
  • 當擁有者離開作用域 (scope),值就會被自動釋放。
  • 變數的「移動 (move)」與「複製 (copy)」依型別不同而有所差異。

1. 作用域與釋放

fn main() {
    {
        let s = String::from("hello");  
        println!("{}", s);
    } 
    // s 在這裡超出作用域,自動釋放記憶體
}

輸出:

hello

s 在區塊結束後自動被回收,無需手動 free。

2. Move(移動)

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;   // 所有權轉移
    println!("{}", s2);
    // println!("{}", s1); // ❌ 編譯錯誤,因為 s1 的所有權已被移走
}

輸出:

hello

在這裡,s1 的值移動到 s2,s1 失效。這和 C++ 的淺拷貝不同。

3. Clone(深拷貝)
如果想要保留兩份資料,可以用 .clone():

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();
    println!("s1 = {}, s2 = {}", s1, s2);
}

輸出:

s1 = hello, s2 = hello

這樣 s1 和 s2 各自持有一份資料。

4. Copy(複製)
基礎型別(整數、浮點數、布林、字元等)不需要 clone,因為它們在賦值時是「複製 (copy)」,而不是「移動 (move)」。

fn main() {
    let x = 5;
    let y = x; // 這裡是 copy,不是 move
    println!("x = {}, y = {}", x, y);
}

輸出:

x = 5, y = 5

這是因為基礎型別存在 stack 上,複製代價很小。

5. Rust vs C++:深拷貝的差別
在 C++ 中,是否是「深拷貝」取決於有沒有實作複製建構函式 (copy constructor)。預設的行為是「淺拷貝」,如果類別內含指標,可能造成重複釋放或懸空指標。若要「深拷貝」,必須自己寫 copy constructor,確保額外配置記憶體並複製內容。在 Rust 中,則更單純,預設是移動 (move),原本的變數會失效;如果需要深拷貝,就必須明確呼叫 .clone()。這樣的區分讓程式行為不會產生模糊空間。

6. 學習心得與補充
今天最大的收穫是第一次真正理解淺拷貝和深拷貝的差別。以前在寫 C/C++ 的時候,雖然知道變數之間可以互相指定,但我並沒有仔細想過它背後是共用同一份資料,還是重新開一塊新的記憶體。今天學到這個概念後,再回頭看 Rust 的 .clone(),就覺得特別清楚又方便。和前幾天學到的變數不可變性、shadowing 甚至型別推導相比,這些規則其實都在往同一個方向走,讓我在寫程式的時候更精確地表達變數是否可改、型別應該是什麼、資料是否需要複製。我覺得這樣的學習過程很有意思,因為每一天學到的新東西都能和之前的內容連起來,慢慢把 Rust 的思維方式拼湊完整。


上一篇
Day 5:控制流程
下一篇
Day 7:借用 (Borrowing) 與參考 (References)
系列文
Rust 30 天養成計畫:從零到 CLI 專案8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言