# Ownership ## Week 0B ---- ## 所有權 + 所有權 Ownership + 一種記憶體管理機制 + 避免記憶體錯誤和資源競爭 ---- ## 其他記憶體管理機制 + Allocate & Free + Garbage Collection ---- ## Allocate & Free 怎麼了 + Memory Leak + 忘記 Free 了 + Double Free + 一個指標 Free 兩次 + Dangling Pointer + 都 Free 了還繼續用 + Null Pointer + 誤用 Null 指標 ---- ## Garbage Collection 怎麼了 + 記憶體佔用 + 不可預測性 + 時間暫停器 ![](https://imgur.com/IiexpAA.png) --- ## 所有權規則 + 每個數值都有個 Owner + 同時間只能有一個 Owner + 當 Owner 離開 Scope 時就會被丟棄 ---- ## 所有權轉移 ```rust= let s1 = String::from("Hello!"); let s2 = s1; // 所有權轉移到 s2 上面 println!("s1: {s1}"); // Error! println!("s2: {s2}"); // OK ``` ---- ## 圖解所有權轉移 ```rust let s1 = String::from("Hello!"); ``` ![](https://i.imgur.com/1anLYgM.png) ---- ## 圖解所有權轉移 ```rust let s2 = s1; // 所有權轉移到 s2 上面 ``` ![](https://i.imgur.com/hv5IJQ9.png) ---- ## Clone ```rust= let mut s1 = String::from("Hello!"); let s2 = s1.clone(); // s1 與 s2 皆可使用 ``` ![](https://i.imgur.com/CoIraWy.png) ---- ## Copy + 具有 Copy 特性的物件沒有所有權的問題 ```rust= fn make_copy(n: i32) { println!("make_copy(), n: {n}") } let x = 5; make_copy(x); println!("After make_copy(), x: {x}") ``` ---- ## Lifecycle ```rust= let s = String::from("Hello, Ownership!"); take_ownership(s); // <= 轉移所有權 fn take_ownership(s: String) { println!("take_ownership(), s: {s}") } // <= 記憶體在此被釋放 println!("s: {s}"); // Error! ``` ---- ## 返還所有權 ```rust= fn give_back(s: String) -> String { println!("In The give_back(), s: {s}"); return s; } let s = String::from("Hello!"); println!("Before give_back(), {s}"); let s = give_back(s); println!("After give_back(), {s}"); ``` ---- ## 返還多組所有權 <div style="font-size: 0.98em"> ```rust= fn give_back(s1: String, s2: String) -> (String, String) { println!("In The give_back(), s1: {s1}, s2: {s2}"); return (s1, s2); } let s1 = String::from("Hello!"); let s2 = String::from("World!"); println!("Before give_back(), s1: {s1}, s2: {s2}"); let (s1, s2) = give_back(s1, s2); println!("After give_back(), s1: {s1}, s2: {s2}"); ``` </div> ---- ## 使用參考 ```rust= fn calc_len(s: &String) -> usize { s.len() } let s_hello = String::from("Hello!"); let len = calc_len(&s_hello); println!("{s_hello} 的長度是 {len}"); ``` ---- ## 可變參考 ```rust= fn calc_len(s: &mut String) -> usize { s.push_str(", World!"); return s.len(); } let mut s = String::from("Hello"); let n = calc_len(&mut s); ``` ---- ## 不能同時有兩個可變參考 + 避免 Race Condition ```rust= let mut s = String::from("hello"); let r1 = &mut s; let r2 = &mut s; println!("{}, {}", r1, r2); ``` ---- ## 也不能同時有可變與不可變參考 ```rust= let mut ss = String::from("hello"); let r1 = &ss; // OK let r2 = &ss; // OK println!("{}, {}", r1, r2); // Still OK Here let r3 = &mut ss; // Error! println!("{}, {}, {}", r1, r2, r3); ```
{"metaMigratedAt":"2023-06-18T00:20:53.426Z","metaMigratedFrom":"YAML","title":"Week 0B - Ownership","breaks":true,"description":"地獄貓旅行團第 11 週心得分享","slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"c7cbb212-2c41-4dfa-8d85-f8e7fa769bf1\",\"add\":3054,\"del\":145}]"}
    118 views
   Owned this note