
- Rust 教程
- Rust - 首頁
- Rust - 簡介
- Rust - 環境搭建
- Rust - HelloWorld 示例
- Rust - 資料型別
- Rust - 變數
- Rust - 常量
- Rust - 字串
- Rust - 運算子
- Rust - 決策機制
- Rust - 迴圈
- Rust - 函式
- Rust - 元組
- Rust - 陣列
- Rust - 所有權
- Rust - 借用
- Rust - 切片
- Rust - 結構體
- Rust - 列舉
- Rust - 模組
- Rust - 集合
- Rust - 錯誤處理
- Rust - 泛型型別
- Rust - 輸入輸出
- Rust - 檔案輸入/輸出
- Rust - 包管理器
- Rust - 迭代器和閉包
- Rust - 智慧指標
- Rust - 併發
- Rust 有用資源
- Rust - 快速指南
- Rust - 有用資源
- Rust - 討論
Rust - 所有權
程式的記憶體可以按以下方式分配:
- 棧
- 堆
棧
棧遵循後進先出的順序。棧儲存大小在編譯時已知的資料值。例如,大小固定的變數 i32 是棧分配的候選者。它的尺寸在編譯時已知。所有標量型別都可以儲存在棧中,因為其大小是固定的。
考慮一個在執行時賦值的字串的例子。此類字串的確切大小在編譯時無法確定。因此,它不是棧分配的候選者,而是堆分配的候選者。
堆
堆記憶體儲存大小在編譯時未知的資料值。它用於儲存動態資料。簡單來說,堆記憶體分配給在程式生命週期中可能發生變化的資料值。與棧相比,堆是記憶體中組織性較差的區域。
什麼是所有權?
Rust 中的每個值都有一個被稱為該值所有者的變數。Rust 中儲存的每個資料都將有一個與其關聯的所有者。例如,在語法let age = 30;
中,age
是值30
的所有者。
每個資料一次只能擁有一個所有者。
兩個變數不能指向同一個記憶體位置。變數將始終指向不同的記憶體位置。
轉移所有權
可以透過以下方式轉移值的所有權:
將一個變數的值賦給另一個變數。
將值傳遞給函式。
從函式返回值。
將一個變數的值賦給另一個變數
Rust 作為一門語言的關鍵賣點是其記憶體安全性。記憶體安全是透過嚴格控制誰可以使用什麼以及何時使用限制來實現的。
考慮以下程式碼片段:
fn main(){ let v = vec![1,2,3]; // vector v owns the object in heap //only a single variable owns the heap memory at any given time let v2 = v; // here two variables owns heap value, //two pointers to the same content is not allowed in rust //Rust is very smart in terms of memory access ,so it detects a race condition //as two variables point to same heap println!("{:?}",v); }
上面的例子聲明瞭一個向量 v。所有權的概念是隻有一個變數繫結到一個資源,要麼v繫結到資源,要麼v2繫結到資源。上面的例子會丟擲一個錯誤:use of moved value: `v`
。這是因為資源的所有權被轉移到了 v2。這意味著所有權從 v 轉移到 v2 (v2=v),並且 v 在移動後無效。
將值傳遞給函式
當我們將堆中的物件傳遞給閉包或函式時,值的所有權也會發生變化。
fn main(){ let v = vec![1,2,3]; // vector v owns the object in heap let v2 = v; // moves ownership to v2 display(v2); // v2 is moved to display and v2 is invalidated println!("In main {:?}",v2); //v2 is No longer usable here } fn display(v:Vec<i32>){ println!("inside display {:?}",v); }
從函式返回值
傳遞給函式的所有權將在函式執行完成後失效。解決此問題的一種方法是讓函式將擁有物件返回給呼叫者。
fn main(){ let v = vec![1,2,3]; // vector v owns the object in heap let v2 = v; // moves ownership to v2 let v2_return = display(v2); println!("In main {:?}",v2_return); } fn display(v:Vec<i32>)->Vec<i32> { // returning same vector println!("inside display {:?}",v); }
所有權和原始型別
對於原始型別,一個變數的內容被複制到另一個變數。因此,不會發生所有權移動。這是因為原始變數比物件需要的資源更少。考慮以下示例:
fn main(){ let u1 = 10; let u2 = u1; // u1 value copied(not moved) to u2 println!("u1 = {}",u1); }
輸出將是 – 10。