50、动态数组(Vectors)
Vectors
静态数组的优点也是他们的缺点:他们的大小必须在编译时预先知道。如果我们尝试创建一个大小仅在运行时已知的数组,我们将会收到编译错误:
let n = 10;
let numbers: [u32; n];
error[E0435]: attempt to use a non-constant value in a constant
--> src/main.rs:3:20
|
2 | let n = 10;
3 | let numbers: [u32; n];
| ^ non-constant value
静态数组并不适合我们的票据管理系统——我们不知道在编译时需要存储多少tickets。显然,动态数组Vec
更适合这一点。
Vec
Vec
是一种可以“增长”的数组类型,由标准库提供同。我们可以使用Vec::new
函数创建一个空数组:
let mut numbers: Vec<u32> = Vec::new();
然后使用push
方法将元素push到vector里:
numbers.push(1);
numbers.push(2);
numbers.push(3);
新值将添加到vector的末尾。
如果在创建的时候知道值,我们也可以使用vec!
宏创建vector。
let numbers = vec![1, 2, 3];
访问元素
用于访问元素的语法与数组相同:
let numbers = vec![1, 2, 3];
let first = numbers[0];
let second = numbers[1];
let third = numbers[2];
注意:索引必须是usize
类型
我们也可以使用get
方法,该方法的返回值是Option<&T>
:
let numbers = vec![1, 2, 3];
assert_eq!(numbers.get(0), Some(&1));
// You get a `None` if you try to access an out-of-bounds index
// rather than a panic.
assert_eq!(numbers.get(3), None);
访问时会进行边界检查,就像数组中的元素那样,它具有O(1)
的时间复杂度。
内存分布
Vec
是一个heap-allocated
(堆分配)的数据结构。
当我们创建Vec
时,它会在堆上分配内存来存储元素。
如果我们运行这个代码:
let mut numbers = Vec::with_capacity(3);
numbers.push(1);
numbers.push(2);
我们可以得到以下的内存布局:
Vec
可以跟踪三件事:
- 指向预留的堆区域的指针。
- vector的长度,即vector中有多少个元素
- vector的容量,即堆上保留的空间中可以容纳的元素数量
这个布局看起来很熟悉:它跟String
完全一样!
这不是一个巧合:在幕后,String
被定义为bytes vector
(字节vector)Vec<u8>
:
#[derive(PartialEq, PartialOrd, Eq, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "String"]
pub struct String {
vec: Vec<u8>,
}
练习
这一节的练习是让我们实现一个斐波那契数列,经典老题了啊。
我也是简单编写了一个函数,算是完美使用到了vec的动态这个特性吧:
// Given a number `n`, return the `n+1`th number in the Fibonacci sequence.
//
// The Fibonacci sequence is defined as follows:
//
// - The first number of the sequence is 0.
// - The second number of the sequence is 1.
// - Every subsequent number is the sum of the two preceding numbers.
//
// So the sequence goes: 0, 1, 1, 2, 3, 5, 8, 13, 21, and so on.
//
// We expect `fibonacci(0)` to return `0`, `fibonacci(1)` to return `1`,
// `fibonacci(2)` to return `1`, and so on.
pub fn fibonacci(n: u32) -> u32 {
// TODO: implement the `fibonacci` function
//
// Hint: use a `Vec` to memoize the results you have already calculated
// so that you don't have to recalculate them several times.
if n == 0 {
0
} else {
let mut nums = Vec::new();
nums.push(0);
nums.push(1);
for i in 1..n {
nums.push(nums[nums.len() - 1] + nums[nums.len() - 2]);
}
*nums.last().unwrap()
}
}
这一节的学习就先到这了。
阅读剩余
版权声明:
作者:CN059
链接:https://www.cn059.com/2025/09/19/50%e3%80%81%e5%8a%a8%e6%80%81%e6%95%b0%e7%bb%84%ef%bc%88vectors%ef%bc%89.html
文章版权归作者所有,未经允许请勿转载。
THE END