# Ownership
## Week 0B
----
## 所有權
+ 所有權 Ownership
+ 一種記憶體管理機制
+ 避免記憶體錯誤和資源競爭
----
## 其他記憶體管理機制
+ Allocate & Free
+ Garbage Collection
----
## Allocate & Free 怎麼了
+ Memory Leak
+ 忘記 Free 了
+ Double Free
+ 一個指標 Free 兩次
+ Dangling Pointer
+ 都 Free 了還繼續用
+ Null Pointer
+ 誤用 Null 指標
----
## Garbage Collection 怎麼了
+ 記憶體佔用
+ 不可預測性
+ 時間暫停器

---
## 所有權規則
+ 每個數值都有個 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!");
```

----
## 圖解所有權轉移
```rust
let s2 = s1; // 所有權轉移到 s2 上面
```

----
## Clone
```rust=
let mut s1 = String::from("Hello!");
let s2 = s1.clone();
// s1 與 s2 皆可使用
```

----
## 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}]"}