Move 有兩種類型的引用
&
&mut
let foo = Foo { x: 3, y: true };
let foo_ref: &Foo = &foo;
let y: bool = foo_ref.y; // reading a field via a reference to the struct
let x_ref: &u64 = &foo.x;
let x_ref_mut: &mut u64 = &mut foo.x;
*x_ref_mut = 42; // modifying a field via a mutable reference
Move 提供了用於創建和擴展引用以及將可變引用轉換為不可變引用的運算符。
e
e
e
字段的不可變引用 f
。e
字段的可變引用 f
。&e.f
and &mut e.f
運算符既可以用於創建對結構的新引用,也可以用於擴展現有引用:
let s = S { f: 10 };
let f_ref1: &u64 = &s.f; // works
let s_ref: &S = &s;
let f_ref2: &u64 = &s_ref.f // also works
在 Struct 篇章有說過,當兩個 Struct 在同一個 Module 時,可以使用多字段表達式拿到。可以同時搭配這邊介紹的可變和不可變運算符。
struct A { b: B }
struct B { c : u64 }
fun f(a: &A): &u64 {
&a.b.c
}
可以讀取可變和不可變引用已生成引用值的副本。
注意,只能編寫可變引用。
為了讀取引用,基礎類型必須具有 copy 能力,防止複製資源值
address 0x3 {
module M {
struct Coin { amount: u64 }
fun copy_resource_via_ref_bad(c: Foo) {
let c_ref = &c;
let counterfeit: Foo = *c_ref; // 會 error, 解決辦法是在 Coin type 加上 copy 能力
}
}
}
為了寫入引用,類型必須具有寫入引用將丟棄舊值 ( drop ) 的能力,此規則可以防止破壞資源值
address 0x3 {
module M {
struct Coin { amount: u64 }
fun destroy_resource_via_ref_bad(ten_coins: Coin, c: Coin) {
let ref = &mut ten_coins;
*ref = c; // not allowed--would destroy 10 coins! 解決辦法是在 Coin type 加上 drop 能力
}
}
}
通過 freeze 推斷,Move 類型檢查器可以將 &mut T
視為 &T
,因為可變引用可以在需要不可變引用的上下文始中使用。
address 0x42 {
module Example {
fun read_and_assign(store: &mut u64, new_value: &u64) {
*store = *new_value
}
fun subtype_examples() {
let x: &u64 = &0;
let y: &mut u64 = &mut 1;
x = &mut 1; // valid
y = &2; // invalid!, 要使用 &mut 2
read_and_assign(y, x); // valid
read_and_assign(x, y); // invalid!
}
}
}
在許多語言都有 Reference, 而 Move 主要使用可變和不可變進行控制,並搭配 type 能力來避免各種開發上的預防錯誤。讓我們 Move to Day13