常用集合——vector
集合的数据存放在堆里,无需在编译时确定大小。
使用vector
vector可存放多个值,Vec<T>
叫做vector。
- 由标准库提供
- 可存储多个值
- 只能存储相同类型的数据
- 值在内存中连续存放
1)创建vector:
- 使用Vec::new函数
let v: Vec<i32> = Vec::new(); // new创建一空的vector,没有元素,所以编译器无法推断出类型,需指明为i32类型
- 使用初始值创建
Vec<T>
,使用vec!宏
let v = vec![1, 2, 3]; // 推断std::vec::Vec<i32>类型
2)更新vector:
- 向Vector添加元素,使用push方法
let mut v = Vec::new();
v.push(1); // 因添加了元素,编译器可推断出类型是Vec<i32>
v.push(2);
3)删除vector:
- 与任何其它struct一样,当Vector离开作用域后,它将被清理,且所有元素也将被清理。
4)读取vector的元素:
- 引用vector里的值的两种方式:索引、get方法。
fn main() {
let v = vec![1, 2, 3];
let t1: &i32 = &v[1];
println!("t1={}", t1);
match v.get(2) {
Some(t2) => println!("t2={}", t2),
None => println!("is None"),
}
}
/*打印结果
t1=2
t2=3
*/
针对越界访问,索引的方式会导致程序崩溃(panic),get的方式会返回None。
fn main() {
let v = vec![1, 2, 3];
match v.get(20) {
Some(t2) => println!("t2={}", t2),
None => println!("is None"),
}
let t1: &i32 = &v[10];
println!("t1={}", t1);
}
/*运行结果
is None
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 10', src\main.rs:
*/
5)所有权和借用规则:
- 不能在同一作用域内同时拥有可变和不可变引用
fn main() {
let mut v = vec![1, 2, 3, 4];
let t1 = &v[1]; // 不可变借用
v.push(5); // 可变借用
println!("t1={}", t1); // 不可变借用
}
/*编译结果
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> src\main.rs:4:5
|
3 | let t1 = &v[1];
| - immutable borrow occurs here
4 | v.push(5);
| ^^^^^^^^^ mutable borrow occurs here
5 | println!("t1={}", t1);
| -- immutable borrow later used here
*/
这是因为v在push后,如果原空间容量不够,则需要重新分配内存,释放原来内存,但t1可能还是指向原来的内存块,为了防止这种问题发生,直接编译时避免这种情况发生。
6)遍历vector的值:
- 使用for循环
fn main() {
let mut v = vec![1, 2, 3];
for i in &mut v {
*i += 2;
}
for i in v {
println!("{}", i);
}
}
/*
3
4
5
*/
使用vector+enum来存储多种数据类型
vector只能存储一种类型,有时需要存放多种类型,则结合enum来完成。因为enum的变体可附加不同类型的数据,enum变体定义在同一个enum类型下。
#[derive(Debug)]
enum TestEnum {
IntNum(i32),
FloatNum(f64),
TextStr(String),
}
fn main() {
let row = vec![
TestEnum::IntNum(3),
TestEnum::TextStr(String::from("test")),
TestEnum::FloatNum(3.14),
TestEnum::IntNum(5),
];
for i in row {
println!("{:?}", i);
}
}
/* 运行结果
IntNum(3)
TextStr("test")
FloatNum(3.14)
IntNum(5)
*/
vector无法存放多种类型的原因是因编译器需要在编译时确定类型,以防止一些操作对某些类型是合法的而对另外一些类型是不合法,而通过enum配合的方式,则在编译时就能确定出类型,也就是提前枚举出了所有类型,能够让运行时正确处理,如果无法详尽枚举出所有类型,则没法定义出enum了。对于无法枚举出所有类型的情况可使用trait对象的方式。