在 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 中最常用的数据结构之一,适用于以下场景:
• 存储可变数量的元素。
• 需要高效的随机访问。
• 需要动态增长或缩小的集合。