0x00 回顾与开篇
上一篇文章主要讲解了Rust的复合数据类型(Compound Types)——数组,元组。这节课继续讲解数据类型——向量(Vector),又称作动态数组。为跟数组区分且方便理解,课程中将把动态数组全部叫作“向量”。上一篇文章只是简单介绍了下数组的概念。
0x01 向量的定义
Vec是一种动态的可变数组,可以在运行时增长或者缩短数组的长度。其签名形式Vec<T>
,T表示任意类型。Vec<T>
叫做T类型的向量。向量的元素保存在堆上,这也是它可以动态增长或者缩短长度的原因。向量中的每个元素都分配有唯一的索引值,同数组一样,索引从0开始计数。
PS:本节课中的代码打印时都添加了 “&” 符号,其与Rust的所有权有关,这里了解即可,后面会详细介绍。
0x02 向量的创建
向量常见的创建方式有以下3种:
1、使用Vec::new()
创建一个空的向量。容量为0
,长度为0
的向量在堆上是不占内存的。通常创建向量时使用mut
修饰,因为向量需要动态增删元素。需要指定类型。
let mut vec_empty: Vec<i32> = Vec::new();
2、[推荐方法] 初始化时为向量指定容量。容量不等于长度,不要跟长度混淆。下面是容量为10的空向量(长度为0)。需要指定类型。
let mut vec_capacity :Vec<i32> = Vec::with_capacity(5);
3、[推荐方法] 使用“宏”创建向量。这种方式的创建方法类似于数组的语法。它也有3种创建方式。
- 创建空的向量。需要指定类型。
let mut vec_marco: Vec<i32> = vec![];
- 创建带有默认元素的向量。支持类型推断。
let mut vec_marco = vec![1, 2, 3, 4, 5];
- 创建指定长度且初始化所有元素的向量。支持类型推断。
// 长度为5,元素初始化为0 let mut vec_marco = vec![0; 5];
0x03 添加元素
使用push
方法在向量的尾部添加新元素。下面的代码是在向量后面追加了元素1
。添加元素需要将向量使用mut
关键字修饰。
let mut vec_push = vec![0; 5]; vec_push.push(1); dbg!(&vec_push);
0x04 修改元素
修改元素,直接使用“变量名称[索引] = 要修改的值”即可重新为元素赋值。下面的代码是将向量的第4个元素(索引值3的元素)的值修改为1。修改元素需要将向量使用mut
关键字修饰。
let mut vec_push = vec![0; 5]; vec_push[3] = 1; dbg!(&vec_push);
0x05 删除元素
Rust中有两种删除向量的元素的方式。删除元素需要将向量使用mut
关键字修饰。
1、通过pop
方法弹出队尾元素。调用pop
方法会返回一个Option
枚举类型。如果数组不为空,则会返回Some(v)
,v
是弹出的值。如果向量为空,则会返回None
(关于Option
这里了解即可)。
示例代码如下:
let mut vec_pop = vec![1]; let pop = vec_pop.pop(); dbg!(pop); let pop = vec_pop.pop(); dbg!(pop);
代码执行结果:
[src\main.rs:31] pop = Some( 1, ) [src\main.rs:33] pop = None
2、通过remove
方法删除元素,需要传入将要删除元素的索引,并且返回删除的元素。这个操作会引发向量元素的移位,被删除元素的后面元素都会相应的左移一位。如果传入的索引大于向量的长度,则会产生程序错误。
示例代码如下:
let mut vec_remove = vec!['w', 'o', 'r', 'l', 'd']; let remove_element = vec_remove.remove(3); dbg!(remove_element); // 索引越界,会发生错误 // let remove_element = vec_remove.remove(5);
代码执行结果:
[src\main.rs:38] remove_element = 'l' // 下面是越界的执行结果 thread 'main' panicked at 'removal index (is 5) should be < len (is 4)', library\alloc\src\vec\mod.rs:1347:13 stack backtrace:
0x06 小结
本篇文章仅仅简单介绍了下向量的创建,修改,以及删除等基础操作。其实,看起来向量的操作并没有很复杂是吧,处理向量的时候还是要注意越界的操作。有关于数组的区别将在下一篇文章具体介绍。源码也将在下一篇文章给出。