導入
第1章の配列は要素数が固定でした。実際には「後から要素を追加していく」ことがほとんどです。それを担うのが Vec<T>(ベクタ)——ヒープ上に確保される、伸び縮み自由な配列です。第3章で見た「スタックに管理情報、ヒープに実データ」の構造を持つ代表例です。
説明
fn main() {
let mut v: Vec<i32> = Vec::new(); // 空のベクタ
v.push(10); // 末尾に追加
v.push(20);
v.push(30);
// vec! マクロで初期値付きで作るのが手軽
let mut nums = vec![1, 2, 3];
nums.push(4);
println!("{:?}", nums); // [1, 2, 3, 4]
println!("要素数: {}", nums.len());
// 添字アクセス(範囲外はパニック)と、安全な get(Option を返す)
println!("先頭: {}", nums[0]);
match nums.get(10) {
Some(v) => println!("{v}"),
None => println!("範囲外"),
}
// 全要素をたどる
for n in &nums { // &nums で借りてループ(所有権を奪わない)
print!("{n} ");
}
println!();
}
Vec::new()またはvec![...]で作成。要素を足すにはmutが必要です。pushで末尾に追加、nums[0]で添字アクセス、getはOptionを返す安全版(第7章)。for n in &nums…&を付けて借用でループします。&なしだとnumsの所有権がループにムーブしてしまい、以後使えなくなります。ここでも所有権の知識が効いてきます。
Vec は要素が増えてヒープの容量(capacity)が足りなくなると、より大きな領域を確保して自動で引っ越します。この面倒を Vec が引き受けてくれるので、私たちは push するだけで済みます。
試すには
for n in nums(& なし)と書くと nums がムーブして、ループ後に nums を使えなくなります。for n in &nums にすると借用なので後でも使えます。コレクションのループでは「借りるか、渡すか」を意識する癖をつけましょう。