言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Rust辞典

  1. トップページ
  2. Rust辞典
  3. Vec::new() / vec![]

Vec::new() / vec![]

対応: Rust 1.0(2015)

RustのVec(ベクタ)は可変長の配列です。『Vec::new()』で空のVecを作成し、『vec![]』マクロで初期値付きのVecを作れます。同じ型の要素を動的に管理するときに使います。

構文

// 空のVecを生成します。
let v: Vec<i32> = Vec::new();

// vec! マクロで初期値を指定して生成します(型推論が効きます)。
let v = vec![1, 2, 3, 4, 5];
let v = vec!["孫悟空", "ベジータ", "ピッコロ"];

// 容量を事前に確保します(パフォーマンス最適化)。
let mut v: Vec<i32> = Vec::with_capacity(100);

// 同じ値で初期化します。
let v = vec![0; 5]; // [0, 0, 0, 0, 0]

// 型変換でVecを生成します。
let v: Vec<i32> = (1..=5).collect(); // [1, 2, 3, 4, 5]

生成方法一覧

記述方法概要
Vec::new()空のVecを生成します(要素型は型注釈で指定します)。
vec![値1, 値2, ...]初期値を持つVecを生成します(型推論あり)。
vec![値; n]同じ値をn個持つVecを生成します。
Vec::with_capacity(n)n要素分のメモリを事前確保してVecを生成します。
イテレータ.collect::<Vec<_>>()イテレータの要素をVecに集めます。
v.capacity()現在確保しているメモリ容量(要素数)を返します。
v.len()現在の要素数を返します。
v.is_empty()Vecが空かどうかを返します。
v[i]i番目の要素にアクセスします(範囲外はパニック)。
v.get(i)i番目の要素をOption<&T>で返します(範囲外はNone)。

サンプルコード

『Vec::new』と『vec!』マクロを使ったベクタの作成方法を確認するサンプルコードです。

sample_vec_new.rs
fn main() {
    // Vec::new() で空のVecを生成します。
    let mut v1: Vec<i32> = Vec::new();
    v1.push(1);
    v1.push(2);
    v1.push(3);
    println!("Vec::new() + push: {:?}", v1);

    // vec! マクロで初期値付きのVecを生成します。
    let v2 = vec![10, 20, 30, 40, 50];
    println!("vec![]: {:?}", v2);

    // 同じ値で初期化します。
    let zeros = vec![0; 5];
    println!("vec![0; 5]: {:?}", zeros);

    // Vec::with_capacity でメモリを事前確保します。
    let mut v3: Vec<i32> = Vec::with_capacity(10);
    println!("\n容量確保後: len={}, capacity={}", v3.len(), v3.capacity());
    for i in 0..5 {
        v3.push(i);
    }
    println!("5要素追加後: len={}, capacity={}", v3.len(), v3.capacity());

    // イテレータからVecを生成します。
    let v4: Vec<i32> = (1..=5).collect();
    println!("\n(1..=5).collect(): {:?}", v4);

    let v5: Vec<i32> = (0..10).filter(|x| x % 2 == 0).collect();
    println!("偶数のみ: {:?}", v5);

    // 要素へのアクセスです。
    println!("\n--- 要素アクセス ---");
    let v = vec![10, 20, 30, 40, 50];
    println!("v[2] = {}", v[2]); // インデックスアクセス

    // 安全なアクセス(get)はOption型を返します。
    match v.get(2) {
        Some(x) => println!("v.get(2) = {}", x),
        None => println!("インデックス範囲外"),
    }
    println!("v.get(10) = {:?}", v.get(10)); // None

    // Vec のメタ情報です。
    println!("\n--- メタ情報 ---");
    println!("len: {}", v.len());
    println!("is_empty: {}", v.is_empty());
    println!("capacity: {}", v.capacity());

    // for ループでの走査です。
    print!("\nfor ループ: ");
    for x in &v {
        print!("{} ", x);
    }
    println!();
}

コンパイルして実行すると次のように出力されます。

rustc vec_new.rs
./vec_new
Vec::new() + push: [1, 2, 3]
vec![]: [10, 20, 30, 40, 50]
vec![0; 5]: [0, 0, 0, 0, 0]

容量確保後: len=0, capacity=10
5要素追加後: len=5, capacity=10

(1..=5).collect(): [1, 2, 3, 4, 5]
偶数のみ: [0, 2, 4, 6, 8]

--- 要素アクセス ---
v[2] = 30
v.get(2) = 30
v.get(10) = None

--- メタ情報 ---
len: 5
is_empty: false
capacity: 5

for ループ: 10 20 30 40 50

よくあるミス

よくあるミス1: Vec::new()で型注釈忘れてコンパイルエラー

Vec::new()では要素の型を型注釈で指定しないとコンパイラが型を推論できずエラーになります。要素を後でpush()する場合は特に注意が必要です。

vec_new_mistake1.rs
fn main() {
    // 型注釈なしで後からpushする場合は型を推論できません。
    let v = Vec::new();
    // v.push(1); // この行を追加すれば推論できますが...

    // emptyのままforに渡すとエラーになります。
    for x in &v {
        println!("{}", x); // error: type annotations needed
    }
}
rustc vec_new_mistake1.rs
error[E0282]: type annotations needed

型注釈を明示するか、vecマクロで初期値を指定します。

vec_new_fix1.rs
fn main() {
    // 型注釈を付けます。
    let mut v1: Vec<i32> = Vec::new();
    v1.push(1);
    v1.push(2);
    println!("{:?}", v1);

    // vec!マクロを使うと型推論が効きます。
    let v2 = vec![1, 2, 3];
    println!("{:?}", v2);

    // collectで型を指定します。
    let v3: Vec<i32> = (1..=5).collect();
    println!("{:?}", v3);
}
rustc vec_new_fix1.rs
./vec_new_fix1
[1, 2]
[1, 2, 3]
[1, 2, 3, 4, 5]

よくあるミス2: for x in v で所有権が移動してVecが使えなくなる

for x in v とすると、v の所有権がループに移動してしまいます。ループ後にvを使おうとするとコンパイルエラーになります。

vec_new_mistake2.rs
fn main() {
    let v = vec![1, 2, 3, 4, 5];

    for x in v { // vの所有権がループに移動します。
        println!("{}", x);
    }

    // vはもう使えません。
    // println!("{:?}", v); // コンパイルエラー
}
rustc vec_new_mistake2.rs
./vec_new_mistake2
1
2
3
4
5

ループ後もvを使いたい場合は&vで参照を渡します。

vec_new_fix2.rs
fn main() {
    let v = vec![1, 2, 3, 4, 5];

    for x in &v { // &vで参照を渡します(所有権は移動しません)。
        println!("{}", x);
    }

    // ループ後もvが使えます。
    println!("合計: {}", v.iter().sum::<i32>());
}
rustc vec_new_fix2.rs
./vec_new_fix2
1
2
3
4
5
合計: 15

概要

『Vec::with_capacity()』でメモリを事前確保しておくと、要素を追加するたびにメモリ再アロケーションが発生するのを防げます。要素数がある程度わかっている場合は使うとパフォーマンスが向上します。

要素アクセスには添字(v[i])と『get()』の2種類があります。添字アクセスは範囲外でパニックしますが、『get()』はOption型を返すため安全に扱えます。ユーザー入力や外部データのインデックスには『get()』を推奨します。

Vecを for ループで走査するときは、要素の所有権を奪わないように &v(参照)を使ってください。&を付けずに for x in v とすると v の所有権が移動してしまいます。

要素の追加・削除は『Vec::push() / pop() / insert() / remove()』を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。