在 Rust 中,Vec<T> 是 Rust 标准库中的一种泛型数据结构,它是一个动态数组,类似于其他语言中的数组列表(如 Python 的list 或 Java 的ArrayList )。
T是一个泛型参数,表示Vec中存储的元素类型。

1.Vec的定义

Vec<T>是一个动态数组,它在堆上分配内存来存储元素。它具有以下特点:

• 动态大小:Vec<T>的大小可以在运行时动态变化,与固定大小的数组(如[T; N])不同。

• 连续内存:Vec<T>的元素存储在连续的内存块中,这使得通过索引访问元素非常高效(时间复杂度为 O(1))。

• 自动管理内存:当Vec<T>的容量不足以容纳更多元素时,它会自动重新分配更大的内存块,并将现有元素复制到新的内存中。

• 所有权语义:Vec<T>拥有其存储的元素,当Vec<T>被丢弃时,它会自动释放其内部的所有元素。

2.Vec的内存布局

Vec<T>内部由三部分组成:

• 指针:指向堆上分配的内存块。

• 长度(len):表示当前存储的元素数量。

• 容量(capacity):表示分配的内存块可以容纳的最大元素数量。

当向Vec<T>中添加元素时,如果当前长度等于容量,Vec<T>会自动进行重新分配,分配更大的内存块,并将现有元素复制到新的内存中。

3.创建 Vec

可以通过以下方式创建Vec<T>

使用vec!

rust 复制代码
let v: Vec<i32> = vec![1, 2, 3, 4, 5]; // 创建一个包含 5 个整数的 Vec
let v: Vec<i32> = Vec::new(); // 创建一个空的 Vec
let v = vec![0; 10]; // 创建一个包含 10 个 0 的 Vec

使用with_capacity方法
如果提前知道Vec<T>的大小,可以通过with_capacity方法预先分配足够的内存,从而避免多次重新分配:

rust 复制代码
let mut v = Vec::with_capacity(10); // 预分配容量为 10
for i in 0..10 {
    v.push(i);
}

4.访问 Vec的元素

可以通过索引访问Vec<T>中的元素,但需要确保索引在有效范围内,否则会导致运行时错误(panic)。

rust 复制代码
let v = vec![1, 2, 3, 4, 5];
println!("{}", v[0]); // 访问第一个元素
println!("{}", v[4]); // 访问最后一个元素

为了安全地访问元素,可以使用get方法,它返回一个Option类型:

rust 复制代码
let v = vec![1, 2, 3, 4, 5];
if let Some(value) = v.get(2) {
    println!("{}", value); // 安全地访问第三个元素
} else {
    println!("Index out of bounds");
}

5.修改 Vec

可以向Vec<T>中添加或删除元素:

添加元素

• 使用push方法向Vec<T>的末尾添加一个元素:

rust 复制代码
  let mut v = vec![1, 2, 3];
  v.push(4); // v 现在是 [1, 2, 3, 4]

删除元素

• 使用pop方法从Vec<T>的末尾移除一个元素,并返回该元素:

rust 复制代码
  let mut v = vec![1, 2, 3];
  if let Some(value) = v.pop() {
      println!("Removed: {}", value); // 输出 "Removed: 3"
  }
  // v 现在是 [1, 2]

插入和删除中间元素

• 使用insert方法在指定位置插入元素:

rust 复制代码
  let mut v = vec![1, 2, 3];
  v.insert(1, 99); // 在索引 1 的位置插入 99,v 变为 [1, 99, 2, 3]

• 使用remove方法从指定位置移除元素:

rust 复制代码
  let mut v = vec![1, 2, 3];
  v.remove(1); // 移除索引为 1 的元素,v 变为 [1, 3]

6.迭代 Vec

可以使用for循环来遍历Vec<T>中的元素:

rust 复制代码
let v = vec![1, 2, 3, 4, 5];
for item in &v {
    println!("{}", item); // 打印每个元素
}

如果需要修改元素,可以使用可变引用:

rust 复制代码
let mut v = vec![1, 2, 3, 4, 5];
for item in &mut v {
    *item += 1; // 将每个元素加 1
}
println!("{:?}", v); // 输出 [2, 3, 4, 5, 6]

7.性能和内存分配

• 容量(Capacity):Vec<T>有一个内部的“容量”(capacity),表示它当前分配的内存大小。当向Vec<T>中添加元素时,如果当前容量不足以容纳新元素,Vec<T>会自动进行重新分配,分配更大的内存块,并将现有元素复制到新的内存中。重新分配的开销较大,因此 Rust 通常会分配比当前元素数量更多的内存,以减少重新分配的频率。

• 性能优化:如果提前知道Vec<T>的大小,可以通过with_capacity方法预先分配足够的内存,从而避免多次重新分配:

rust 复制代码
  let mut v = Vec::with_capacity(10); // 预分配容量为 10
  for i in 0..10 {
      v.push(i);
  }

8.Vec的用途

Vec<T>是 Rust 中最常用的数据结构之一,适用于以下场景:

• 存储可变数量的元素。

• 需要高效的随机访问。

• 需要动态增长或缩小的集合。