Move VM 實現了類似 Rust 的所有權系統,最好的解釋是在 Rust Book 中 (連結在最下面)。
簡單來說,就是 Move 透過所有權系統來管理內存,該系統具有一組編譯器檢查的規則,如果違反則程序將無法編譯。
每個變量只有一個所有者範圍,當所有者範圍結束時,擁有的變量將被刪除
Owner 是一個擁有變量的作用域,變量既可以在此範圍內定義,也可以作為參數傳遞到範圍內。
Move 中唯一著作用域是函數。
每個變量只有一個所有者,當一個變量作為參數傳遞給函數時,該函數將成為新的所有者,並解該變量不再屬於第一個函數。
script {
use {{sender}}::M;
fun main() {
// Module::T is a struct
let a : Module::T = Module::create(10);
// 變量 a 傳遞到 main function, 之後的任何地方都無法再取的 a
M::value(a);
// a 已不被 main function 擁有,會出現錯醋
M::value(a);
}
}
我們看一下 value function 內部發生了什麼。
module M {
// create_fun skipped
struct T { value: u8 }
public fun create(value: u8): T {
T { value }
}
// value function 取得參數控制權
public fun value(t: T): u8 {
// 可以在 function 內部任何地方使用 t
t.value
}
// function 結束, t 被 drop, 只有 type 是 u8 的值回傳
// t 被刪掉,不存在
}
如果不想讓原本參數的值被 drop 掉,我們可以返回一個帶有原始變量和結果的元祖 (T, u8) ,不過 Move 有一個更好的解決方案。
首先,您需要了解 Move VM 的工作原理,以及將值傳遞給函數時會發生什麼。VM 中有兩個字節碼指令:MoveLoc
和 CopyLoc
- 它們都可以分別手動使用關鍵字 move
和 copy
。
如果您需要將值傳遞給函數(它正在被移動的位置)並保存變量的副本,可以使用關鍵字copy
。
script {
...
fun main() {
let a : Module::T = Module::create(10);
// 我們使用 copy 將 local 變量 a 複製到函數裡當參數
M::value(copy a);
M::value(a); // local 變量 a 一樣可以使用
}
}
通過複製一個值,我們複製了它並增加了我們程序的內存大小,因此可以使用它 - 但是當複製大量數據時,它可能會在內存方面變得昂貴。請記住 - 在區塊鏈中,每個字節都很重要並影響執行價格,因此copy
一直使用可能會花費很多 gas 費用。
因此我們需要搭配上篇所介紹的 Reference 來避免不必要的複製。
讓我們 Move to Day14
相關連結:
Rust Book: https://doc.rust-lang.org/stable/book/ch04-01-what-is-ownership.html