Skip to main content

向量 (Vector)

vector<T> 是 Move 提供的唯一原始集合型別。vector<T> 是由 T 組成的同質集合,可透過在「末端」推入/彈出值來擴張或縮小。

vector<T> 可使用任何型別 T 進行具現化。例如,vector<u64>、vector<address>、vector<0x42::my_module::MyData> 與 vector<vector<u8>> 都是有效的向量型別。

字面值 (Literals)​

一般 vector 字面值 (General vector Literals)​

可使用 vector 字面值建立任何型別的向量。

語法型別說明
vector[]vector[]: vector<T>,其中 T 為任一單一非參考型別空向量
vector[e1, ..., en]vector[e1, ..., en]: vector<T>,其中 e_i: T,且 0 < i <= n 與 n > 0包含 n 個元素的向量(長度為 n)

在這些情況中,vector 的型別會從元素型別或向量的使用方式推斷而得。若無法推斷型別,或只是為了讓內容更清楚,可以明確指定型別:

vector<T>[]: vector<T>
vector<T>[e1, ..., en]: vector<T>

向量字面值範例 (Example Vector Literals)​

(vector[]: vector<bool>);
(vector[0u8, 1u8, 2u8]: vector<u8>);
(vector<u128>[]: vector<u128>);
(vector<address>[@0x42, @0x100]: vector<address>);

vector<u8> 字面值 (vector<u8> literals)​

Move 中向量的一個常見使用情境是表示「位元組陣列」,其以 vector<u8> 表示。這些值通常用於密碼學用途,例如公開金鑰或雜湊結果。這些值十分常見,因此提供了特定語法,讓值更容易閱讀,而不必使用必須以數值形式指定每個個別 u8 值的 vector[]。

目前支援兩種 vector<u8> 字面值:位元組字串 與 十六進位字串。

位元組字串 (Byte Strings)​

位元組字串是以 b 為前綴的帶引號字串字面值,例如 b"Hello!\n"。

這些是允許跳脫序列的 ASCII 編碼字串。目前支援的跳脫序列如下:

跳脫序列說明
\n換行(或換行字元)
\r歸位字元
\t定位字元
\\反斜線
\0空字元
\"引號
\xHH十六進位跳脫,插入十六進位位元組序列 HH

十六進位字串 (Hex Strings)​

十六進位字串是以 x 為前綴的帶引號字串字面值,例如 x"48656C6C6F210A"。

每對範圍從 00 到 FF 的位元組都會解讀為十六進位編碼的 u8 值。因此,每一對位元組都對應結果 vector<u8> 中的一個項目。

字串字面值範例 (Example String Literals)​

fun byte_and_hex_strings() {
assert!(b"" == x"", 0);
assert!(b"Hello!\n" == x"48656C6C6F210A", 1);
assert!(b"\x48\x65\x6C\x6C\x6F\x21\x0A" == x"48656C6C6F210A", 2);
assert!(
b"\"Hello\tworld!\"\n \r \\Null=\0" ==
x"2248656C6C6F09776F726C6421220A200D205C4E756C6C3D00",
3
);
}

操作 (Operations)​

vector 透過 Move 標準函式庫中的 std::vector 模組支援下列操作:

函式說明會中止?
vector::empty<T>(): vector<T>建立可儲存型別 T 值的空向量永不
vector::singleton<T>(t: T): vector<T>建立包含 t、大小為 1 的向量永不
vector::push_back<T>(v: &mut vector<T>, t: T)將 t 加入 v 的末端永不
vector::pop_back<T>(v: &mut vector<T>): T移除並回傳 v 中的最後一個元素若 v 為空
vector::borrow<T>(v: &vector, i: u64): &T回傳索引 i 處 T 的不可變參考若 i 超出範圍
vector::borrow_mut<T>(v: &mut vector<T>, i: u64): &mut T回傳索引 i 處 T 的可變參考若 i 超出範圍
vector::destroy_empty<T>(v: vector<T>)刪除 v若 v 不為空
vector::append<T>(v1: &mut vector<T>, v2: vector<T>)將 v2 中的元素加入 v1 的末端永不
vector::contains<T>(v: &vector, e: &T): bool若 e 位於向量 v 中則回傳 true,否則回傳 false永不
vector::swap<T>(v: &mut vector<T>, i: u64, j: u64)交換向量 v 中第 i 與第 j 個索引位置的元素若 i 或 j 超出範圍
vector::reverse<T>(v: &mut vector<T>)就地反轉向量 v 中元素的順序永不
vector::index_of<T>(v: &vector, e: &T): (bool, u64)若 e 位於向量 v 的索引 i 處,則回傳 (true, i);否則回傳 (false, 0)永不
vector::remove<T>(v: &mut vector<T>, i: u64): T移除向量 v 的第 i 個元素,並位移所有後續元素。此操作為 O(n),且會保留向量中的元素順序若 i 超出範圍
vector::swap_remove<T>(v: &mut vector<T>, i: u64): T將向量 v 的第 i 個元素與最後一個元素交換,接著彈出該元素。此操作為 O(1),但不會保留向量中的元素順序若 i 超出範圍

未來可能會加入更多操作。

範例 (Example)​

use std::vector;

let mut v = vector::empty<u64>();
vector::push_back(&mut v, 5);
vector::push_back(&mut v, 6);

assert!(*vector::borrow(&v, 0) == 5, 42);
assert!(*vector::borrow(&v, 1) == 6, 42);
assert!(vector::pop_back(&mut v) == 6, 42);
assert!(vector::pop_back(&mut v) == 5, 42);

銷毀與複製 vector (Destroying and copying vectors)​

vector<T> 的某些行為取決於元素型別 T 的能力。例如,包含不具備 drop 能力元素的向量,無法像上述範例中的 v 一樣隱含捨棄——必須使用 vector::destroy_empty 明確銷毀。

請注意,除非 vec 包含零個元素,否則 vector::destroy_empty 會在執行階段中止:

fun destroy_any_vector<T>(vec: vector<T>) {
vector::destroy_empty(vec) // 刪除此行將造成編譯器錯誤
}

但捨棄包含具備 drop 能力元素的向量時不會發生錯誤:

fun destroy_droppable_vector<T: drop>(vec: vector<T>) {
// 有效!
// 不需要明確執行任何操作來銷毀向量
}

同樣地,除非元素型別具備 copy,否則向量無法複製。換言之,僅當 T 具備 copy 時,vector<T> 才具備 copy。請注意,若有需要,它會被隱含複製:

let x = vector[10];
let y = x; // 隱含複製
let z = x;
(y, z)

請記住,複製大型向量可能成本高昂。若這是需要考量的問題,為預定的使用方式加上註記可避免意外複製。例如:

let x = vector[10];
let y = move x;
let z = x; // 錯誤!x 已被移動
(y, z)

如需更多詳細資訊,請參閱型別能力與泛型章節。

所有權 (Ownership)​

如上文所述,只有元素可複製時,vector 值才能複製。在此情況下,可透過 copy 或解參考 *執行複製。