15_rust的常用集合_vector

发布时间 2023-10-24 16:36:28作者: UFOFCZ

常用集合——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对象的方式。