Rustのベクター(Vec)で可変長配列を扱う方法

先生

RustのVecを使いこなして、可変長配列を自由自在に操ろう!

RustのVecとは?可変長配列の基本

Rustにおいて、Vec(ベクター)は、可変長の配列を扱うための基本的なデータ構造です。Vecは、要素を連続したメモリ領域に格納し、必要に応じて自動的にサイズを拡張または縮小します。これにより、コンパイル時にはサイズが確定していないデータの集合を効率的に扱うことができます。

C++におけるstd::vectorや、Pythonにおけるリストと似たような役割を担うものだと考えると理解しやすいでしょう。

VecはRustの標準ライブラリstd::vecに定義されており、所有権の概念と組み合わせることで、安全かつ効率的なメモリ管理を実現します。

Vecの生成と初期化

Vecを生成するには、Vec::new()メソッドを使用します。これにより、空のVecが作成されます。

let mut my_vec: Vec<i32> = Vec::new();

Vecを初期化する際には、vec!マクロを使用すると便利です。このマクロを使うと、初期値を指定してVecを生成できます。

let mut my_vec: Vec<i32> = vec![1, 2, 3, 4, 5];

また、あるサイズで初期化し、すべての要素を特定の値で埋めることも可能です。

let mut my_vec: Vec<i32> = vec![0; 10]; // 10個の要素を持ち、すべて0で初期化

要素の追加、削除、アクセス

Vecに要素を追加するには、push()メソッドを使用します。push()メソッドは、Vecの末尾に要素を追加します。

my_vec.push(6);

Vecから要素を削除するには、pop()メソッドを使用します。pop()メソッドは、Vecの末尾の要素を削除し、その値を返します。Vecが空の場合はNoneを返します。

let last_element = my_vec.pop();

Vecの要素にアクセスするには、インデックスを使用します。ただし、Rustでは、存在しないインデックスにアクセスするとpanicが発生するため、注意が必要です。get()メソッドを使用すると、安全に要素にアクセスできます。get()メソッドは、指定されたインデックスに要素が存在する場合はSome(value)を、存在しない場合はNoneを返します。

let first_element = my_vec[0]; // panicの可能性あり
let first_element = my_vec.get(0); // 安全なアクセス

要素の挿入にはinsert()メソッド、削除にはremove()メソッドが利用できます。insert()は指定したインデックスに要素を挿入し、remove()は指定したインデックスの要素を削除します。

my_vec.insert(2, 10); // インデックス2に10を挿入
my_vec.remove(3);  // インデックス3の要素を削除

Vecのイテレーション

Vecの要素を順番に処理するには、forループを使用します。Vecはイテレータを実装しているため、非常に簡単に要素を列挙できます。

for element in &my_vec { // 参照イテレータ
    println!("{}", element);
}

所有権を移動させずに要素を変更したい場合は、ミュータブルな参照イテレータを使用します。

for element in &mut my_vec {
    *element += 1; // 各要素に1を加算
}

Vecの容量と再割り当て

Vecは、要素を追加する際に、必要に応じて自動的にメモリを再割り当てします。この再割り当ては、パフォーマンスに影響を与える可能性があるため、事前にVecの容量を予約しておくことが推奨されます。capacity()メソッドで現在の容量を、reserve()メソッドで追加の容量を予約できます。

let mut my_vec: Vec<i32> = Vec::new();
my_vec.reserve(100); // 100個の要素を格納できる容量を予約

Vecの応用例

Vecは、動的に変化するデータの集合を扱う必要がある場合に非常に役立ちます。例えば、ユーザーからの入力を格納したり、ファイルから読み込んだデータを格納したりするのに使用できます。

use std::io;

fn main() {
    let mut inputs: Vec<String> = Vec::new();

    println!("Enter lines of text (enter 'q' to quit):");

    loop {
        let mut line = String::new();
        io::stdin().read_line(&mut line).expect("Failed to read line");
        let line = line.trim();

        if line == "q" {
            break;
        }

        inputs.push(line.to_string());
    }

    println!("You entered:");
    for input in &inputs {
        println!("{}", input);
    }
}

参考リンク

まとめ

この記事では、RustのVecについて、基本的な使い方から応用例までを解説しました。Vecは、可変長配列を扱うための強力なツールであり、Rustプログラミングにおいて不可欠な要素です。Vecをマスターすることで、より効率的で安全なプログラムを作成できるようになるでしょう。