iT邦幫忙

2022 iThome 鐵人賽

DAY 6
0
Modern Web

30天學習Tauri系列 第 6

6.Rust-lang (三)

  • 分享至 

  • xImage
  •  

關於rust中變數的所有權

一般的程式語言的變數都有其所屬的作用域(scope,能引用到這個變數的範圍),而在rust中也有,但rust變數可以選擇將變數**借出(borrow)給其他的scope,也可以將變數的所有權整個轉移(move)**出去。而轉移出去的變數別人不還的話是拿不回來的,但借出去的變數可以,因為是暫時給別人使用。

rust-lang playground

所有權規則:

  • Rust 中每個數值都會有一個變數作為它的owner。
  • 同時間只能有一個owner。
  • 當owner離開作用域(scope)時,數值就會被丟棄

我們透過String Type來觀察儲存在Heap上的資料,並研究 Rust 是如何知道要清理資料的

為何String可變的,但char卻不行?

兩者最主要的差別在於它們對待記憶體的方式。
( 1 )char在編譯時可以知道它的內容,所以能寫死在最終執行檔。
( 2 )String為了支援可變性,所以需要再Heap上分配一塊編譯時未知大小的記憶體空間來儲存內容。也是就是:

  • 記憶體分配器必須在執行時請求記憶體
  • 我們不再需要這個 String 時,我們需要以某種方法將此記憶體還給分配器
fn main() {
		// ::讓我們可以將from函式置於String型別的namespace下
    let mut s = String::from("hello"); // s在此開始視為有效

		// 使用 s
    s.push_str(", world!"); // push_str() 將char加到string後面

    println!("{}", s); // print `hello, world!`
} // 此作用域結束 s 不再有效

當s離開scope時,我們就可以很自然地將String所需要的記憶體釋放回分配器。

當變數離開作用域時,Rust 會幫我們呼叫一個特殊函式drop,來釋放記憶體。(Rust 會在大括號結束時自動呼叫 drop)

1.變數與資料互動的方式:Move

// 把5賦值給x,然後copy一份x的值給y,並且由於是固定大小的值,所以這x和y的值兩個都會推入heap中
let x = 5;
let y = x;
// 由於string並非固定大小,會透過記憶體分配器來管理記憶體大小。
//
// x透過指標指向"分配的記憶體空間(heap裡)",並記錄長度和容量
// 所以當x賦值給x2時,我們是將x2的指標指向"相同的記憶體空間位置"
// 而不是拷貝整組資料(x2不會自己再請求分配空間,而是參考x)
let x = String::from("hello");
let x2 = x;
let x = String::from("Hello");
let x2 = x;

println!("{}, world!", x);

我們能看到出現錯誤
rust-lang playground
https://ithelp.ithome.com.tw/upload/images/20220921/20108931RwZ5xsgv8a.png

也就是我們把變數給送了出去,離開了我們的scope,所以我們接著無法使用。

為何無法使用?rust防止並避免你進行"無效的引用"操作

當我們的變數離開scope時,Rust會自動呼叫drop來清理該變數在heap上的資料。

而我們知道x和x2是參考同一組data,如果沒有藉由Move機制,會有一個問題,就是x和x2兩個人離開scope:

x變數裡的資料被釋放;x2變數裡的資料被釋放。

兩個人都嘗試釋放相同的記憶體位置(資料區塊),會出現雙重釋放(Double free)的問題,很容易造成重複清除記憶體,導致資料損壞。

所以,我們透過move操作,讓x被移動到x2,來解決問題,來讓只有x2離開scope時,會釋放記憶體。

2.變數與資料互動的方式:克隆(Clone)

那如果我們想拷貝整份資料,而不是參考別人的資料的話,那怎麼辦?我們可以透過Clone來達成。Rust有個特別功能叫做Copy trait,能用在標記像是整數這樣存在heap上的型別。

當一個data type有Copy特徵,那麼"在一個變數賦值給其他變數後仍然會是有效的"。

因為他不是轉移所有權,而是透過讓另一個變數自己去申請空間(不跟他人共用,也就是參考)並將變數整個資料拷貝下來給自己使用

詳細的Copy trait可以去閱讀docs來更加的了解。這邊只簡單介紹

...續

今天簡單介紹Rust中將變數所有權轉移(Move)出去,明天會接續介紹Borrow


上一篇
5.Rust-lang (二)
下一篇
7.Rust-lang (四)
系列文
30天學習Tauri30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言