向量
向量是 Move 中用于存储动态大小元素集合的内建方式。它们类似于其他编程语言中的动态数组,但具有 Move 的类型安全和能力限制。向量是 Move 标准库的重要组成部分,支持多种高效操作。
向量语法
向量的类型通过 vector
关键字定义,其元素类型写在尖括号 <...>
中。向量的元素可以是任何有效的 Move 类型,包括基本类型、结构体,甚至其他向量。
定义和初始化向量
- 空向量 使用
vector[]
初始化空向量。元素类型必须明确指定,或者通过上下文推断。
move
let empty: vector<bool> = vector[]; // 空布尔向量
- 非空向量 使用
vector[...]
初始化带有初始值的向量。
move
let v: vector<u8> = vector[1, 2, 3]; // 包含 u8 元素的向量
- 嵌套向量 向量的元素可以是其他向量。
move
let vv: vector<vector<u8>> = vector[vector[1, 2], vector[3, 4]]; // 二维向量
类型推断
如果上下文能够推断出元素类型,可以省略显式类型声明:
move
let v = vector[1, 2, 3]; // 推断为 vector<u8>
向量操作
Move 标准库的 std::vector
模块提供了操作向量的函数。这些操作包括:
- 追加元素:
push_back
将一个新元素添加到向量的末尾。
move
let mut v = vector[10, 20];
v.push_back(30); // v = vector[10, 20, 30]
- 移除元素:
pop_back
从向量末尾移除一个元素,并返回该元素。如果向量为空,则会触发运行时错误。
move
let mut v = vector[10, 20, 30];
let last = v.pop_back(); // last = 30, v = vector[10, 20]
- 获取长度:
length
返回向量中元素的数量。
move
let v = vector[10, 20, 30];
assert!(v.length() == 3);
- 检查空向量:
is_empty
如果向量为空,返回true
。
move
let v = vector[];
assert!(v.is_empty());
- 移除指定位置元素:
remove
删除指定索引的元素,后续元素前移填补空缺。
move
let mut v = vector[10, 20, 30];
let removed = v.remove(1); // removed = 20, v = vector[10, 30]
- 销毁空向量:
destroy_empty
对于没有drop
能力的类型,必须显式调用destroy_empty
来销毁空向量。
move
let v: vector<u8> = vector[];
v.destroy_empty();
注意事项
销毁不可丢弃类型向量
如果向量的元素类型不具备 drop
能力,那么即使是空向量,也不能直接忽略。必须显式调用 destroy_empty
:
move
public struct NoDrop {} // 没有 `drop` 能力
#[test]
fun test_destroy_empty() {
let v: vector<NoDrop> = vector[]; // 创建空向量
v.destroy_empty(); // 必须显式销毁
}
示例:完整向量操作
以下是综合使用向量的示例:
move
#[test]
fun test_vector_operations() {
let mut v: vector<u8> = vector[1, 2, 3];
assert!(v.length() == 3);
v.push_back(4); // 添加元素
assert!(v.pop_back() == 4); // 移除并返回末尾元素
let removed = v.remove(1); // 移除第二个元素
assert!(removed == 2);
assert!(v.length() == 2);
assert!(!v.is_empty());
}
扩展:嵌套向量
对于嵌套向量,操作与单层向量一致,但需要注意嵌套层级:
move
#[test]
fun test_nested_vector() {
let mut vv: vector<vector<u8>> = vector[vector[1, 2], vector[3, 4]];
vv[1].push_back(5); // 向第二个子向量添加元素
assert!(vv[1] == vector[3, 4, 5]);
}
性能和能力限制
- 动态大小 向量支持动态大小调整,但需要注意每次操作可能涉及内存重新分配,影响性能。
- 类型安全 向量的类型必须一致,无法存储不同类型的元素。
- 能力限制 Move 编译器会根据元素类型的能力限制(如
copy
或drop
),对向量操作施加约束。例如,没有drop
能力的类型无法隐式销毁。