所有权(Ownership)是 Move 语言的核心特性,用于在编译期保证资产安全、防止双重支付。本文介绍所有权的基本规则、移动(Move)语义如何使原变量失效,以及 copy 能力如何让值可以被复制而非转移。
1. 所有权(Ownership)
在 Move 语言中,为了保证资产安全(防止双重支付),有如下规则:
- 每个值都有一个所有者(owner)。
- 对于不实现
Copy 的类型,同一时间只能有一个所有者(即移动语义)。
- 当所有者离开作用域时,值会被自动丢弃,内存释放。
2. 移动(Move)
基于”只能有一个所有者”的规则,当我们把一个变量赋值给另一个变量时,所有权会发生转移。原变量会立即失效。这被称为 Move(移动)。
2.1 所有权的转移
假设我们的 Student 结构体只有 drop 能力:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public struct Student has drop { ... }
public fun test_ownership() { let s1 = create_student(18, true, 80, 90);
let s2 = s1;
let age = s1.age;
let age2 = s2.age; }
|
2.2 内存发生了什么?
1 2 3 4 5 6 7 8 9 10
| 栈 (Stack) 堆 (Heap) +------------------+ +------------------+ | 变量 s1 | ❌ | Student 结构体 | | (已失效/Invalid) | - - - -> | | +------------------+ | age: 18 | | isMale: true | +------------------+ | | | 变量 s2 | =======> | | | (新所有者) | +------------------+ +------------------+
|
3. Copy 能力
有些数据(如普通的成绩单、配置信息)并不需要严格的”唯一性”。我们希望在赋值时,复制一份新的数据,保留原数据。这时需要使用 copy 能力。
3.1 复制(Copy)
注意: 类似于 drop,如果外层结构体需要 copy,内部嵌套的结构体(Grades)也必须有 copy。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public struct Student has drop, copy { age: u8, isMale: bool, grades: Grades, }
public struct Grades has drop, copy { literature: u64, math: u64, }
public fun test_copy() { let s1 = create_student(18, true, 80, 90);
let s2 = s1;
let age1 = s1.age; let age2 = s2.age; }
|
3.2 内存发生了什么?
1 2 3 4 5 6 7 8 9 10 11 12 13
| 栈 (Stack) 堆 (Heap) +------------------+ +------------------+ | 变量 s1 | -------> | Student (A) | | | | age: 18 | +------------------+ +------------------+
Let s2 = s1 (Copy) ⬇️
+------------------+ +------------------+ | 变量 s2 | -------> | Student (B) | | | | age: 18 | +------------------+ +------------------+
|
4. 什么时候用 Copy?
- Move (默认):适用于资产(如 Token、NFT)。像现金一样,给出去就没有了。
- Copy:适用于普通数据(如
u64、状态配置)。像文档一样,可以复印无数份。