複合型

複合型は、複数の値をまとめて一つの型として扱うことができるデータ型です。Rustには主に以下の複合型があります。

タプル型

タプル型は、異なる型の値をまとめて一つのグループとして扱います。タプルはカンマ区切りの値を丸括弧で囲んで作成します。 また、タプルから値を取り出すには、パターンマッチングを使用して分解することができます。

fn main() {
    let tuple: (i32, f64, char) = (42, 3.14, 'a');
    let (x, y, z) = tuple; // パターンマッチングで値を取り出す
    println!("Tuple: ({}, {}, {})", x, y, z);
}

タプルから特定の要素を取り出すには、インデックスも使用できます。インデックスは0から始まります。

fn main() {
    let tuple: (i32, f64, char) = (42, 3.14, 'a');
    println!("First element: {}", tuple.0);
    println!("Second element: {}", tuple.1);
    println!("Third element: {}", tuple.2);
}

配列型

配列型は、同じ型の値を固定長の配列として扱います。配列は角括弧で囲んで作成します。 ベクタを生成するには、vec!マクロやVec::newメソッドを使用します。

fn main() {
    let array: [i32; 3] = [1, 2, 3];
    println!("Array: {:?}", array);
    println!("First element: {}", array[0]);
    println!("Second element: {}", array[1]);
    println!("Third element: {}", array[2]);
}

ベクタ型

ベクタ型(Vec<T>)は、動的にサイズを変更できる可変長の配列です。

  • 可変長: 実行時にサイズを変更できます。
  • ヒープメモリ: 要素はヒープに格納されます。
  • 型安全: ベクタ内のすべての要素は同じ型でなければなりません。
#![allow(unused)]
fn main() {
// vec!マクロを使用
let v = vec![1, 2, 3];

// Vec::newを使用
let mut v: Vec<i32> = Vec::new();
v.push(1);
v.push(2);
v.push(3);
}

ベクタの操作

ベクタには多くの便利なメソッドがあります。以下にいくつかの例を示します:

  • 要素の追加: push
  • 要素の削除: pop
  • 要素の挿入: insert
  • 要素の削除: remove
  • 長さの取得: len
  • 空チェック: is_empty
  • 全要素の削除: clear
fn main() {
    let mut v = vec![1, 2, 3];
    v.push(4); // 末尾に要素を追加
    v.pop(); // 末尾の要素を削除
    v.insert(1, 10); // インデックス1に要素を挿入
    v.remove(1); // インデックス1の要素を削除
    println!("ベクタの長さ: {}", v.len()); // 長さを取得
    println!("ベクタは空か?: {}", v.is_empty()); // 空チェック
    v.clear(); // 全要素を削除
}

初心者の理解:それぞれのデメリット

タプル型は要素数、配列型は長さと型が固定されているため、柔軟なデータ管理が難しいです。 一方、ベクタ型は動的にサイズを変更できるため、メモリの再割り当てが発生することがあり、これがパフォーマンスに影響を与えることがあります。また、ベクタの初期化には配列よりもコストがかかる場合があります。

特徴

タプル型配列型ベクタ型
要素異なる型の要素を持つことができる同じ型の要素のみ同じ型の要素のみ
要素数固定固定(長さ)可変
要素へのアクセスインデックスまたはパターンマッチングインデックスインデックス
用途関数から複数の値を返す、一時的なデータのグループ化固定長のデータ、ループ処理やインデックスを使ったアクセス動的にサイズを変更できるデータ、可変長のデータ、頻繁な追加や削除が必要な場合