如何使用Rust的向量存储值列表

 更新时间:2025年02月26日 11:07:22   作者:Hello.Reader  
本文介绍了在Rust中使用向量存储值列表的方法,包括创建、更新、读取、遍历、存储多种类型以及内存释放等方面,向量是Rust中常用且强大的集合类型,熟练掌握其用法有助于编写高效且安全的代码

1. 创建新的向量

Rust 提供了两种常用方式来创建向量:

使用 Vec::new

当你需要创建一个空的向量时,可以调用 Vec::new

注意,由于向量中还没有元素,编译器无法自动推断向量中元素的类型,这时通常需要添加类型注解。

例如:

fn main() {
    // 创建一个空的 Vec<i32>
    let mut v: Vec<i32> = Vec::new();

    // 向向量中添加元素
    v.push(5);
    v.push(6);
    v.push(7);
    v.push(8);

    println!("Vector: {:?}", v);
}

使用 vec! 宏

如果你希望一开始就初始化向量并指定初始值,可以使用 vec! 宏。

Rust 会根据给定的初始值自动推导向量元素的类型:

fn main() {
    // 创建一个包含初始值 1, 2, 3 的向量,类型会被推断为 Vec<i32>
    let v = vec![1, 2, 3];

    println!("Vector: {:?}", v);
}

2. 更新向量

向量是动态大小的数据结构,可以通过调用 push 方法将新的元素添加到向量中。

需要注意的是,如果想要修改向量的内容,变量必须声明为可变(mut):

fn main() {
    let mut v = vec![1, 2, 3];

    // 添加元素到向量末尾
    v.push(4);
    v.push(5);

    println!("Updated vector: {:?}", v);
}

3. 读取向量中的元素

读取向量元素主要有两种方法:使用索引语法和使用 get 方法。

3.1 使用索引语法

使用索引语法可以直接获取向量中指定位置的元素。

例如:

fn main() {
    let v = vec![10, 20, 30, 40, 50];

    let third: &i32 = &v[2]; // 注意:索引从 0 开始,所以索引 2 表示第三个元素
    println!("The third element is: {}", third);
}

注意:如果索引超出向量范围(例如访问一个不存在的元素),使用索引语法会导致程序 panic,从而崩溃。

3.2 使用 get 方法

get 方法会返回一个 Option<&T>,在访问超出范围时返回 None 而不是 panic,从而可以通过匹配(match)或其他方式来安全处理这种情况:

fn main() {
    let v = vec![10, 20, 30, 40, 50];

    // 试图获取索引为 100 的元素
    match v.get(100) {
        Some(value) => println!("The element is: {}", value),
        None => println!("There is no element at index 100."),
    }
}

4. 向量与借用检查器

Rust 的借用规则保证了对向量元素的引用安全。

举个例子,如果我们在持有某个元素的不可变引用时尝试修改向量,就会触发借用检查器报错:

fn main() {
    let mut v = vec![1, 2, 3];

    // 获取第一个元素的不可变引用
    let first = &v[0];
    // 尝试向向量中添加一个新元素
    // v.push(4); // 这行代码会导致编译错误,因为不可变引用和可变操作不能共存

    println!("The first element is: {}", first);
}

原因在于:向量在内存中是连续存储的,添加新元素可能会导致内存重新分配,进而使已有的引用失效。借用检查器可以在编译期间捕捉到这种潜在的安全问题。

5. 遍历向量

遍历向量通常使用 for 循环。可以选择不可变遍历或者可变遍历以修改元素。

5.1 不可变遍历

下面的代码演示了如何通过不可变引用遍历向量中的每个元素并打印出来:

fn main() {
    let v = vec![100, 32, 57];

    for i in &v {
        println!("The value is: {}", i);
    }
}

5.2 可变遍历

如果需要修改向量中的每个元素,则可以通过可变引用来遍历:

fn main() {
    let mut v = vec![100, 32, 57];

    for i in &mut v {
        // 使用解引用操作符 * 来修改引用指向的值
        *i += 50;
    }

    println!("Modified vector: {:?}", v);
}

6. 使用枚举存储不同类型的值

向量要求所有元素必须是相同类型的,但在某些情况下,你可能需要在同一个向量中存储不同类型的值。为了解决这一问题,可以定义一个枚举,将所有可能的类型都作为枚举的不同变体,然后将枚举实例存储在向量中:

// 定义一个枚举,表示可能出现的不同类型
enum SpreadsheetCell {
    Int(i32),
    Float(f64),
    Text(String),
}

fn main() {
    // 创建一个存储 SpreadsheetCell 枚举的向量
    let row = vec![
        SpreadsheetCell::Int(3),
        SpreadsheetCell::Float(10.12),
        SpreadsheetCell::Text(String::from("blue")),
    ];

    // 遍历向量,并根据每个枚举的变体进行匹配处理
    for cell in row {
        match cell {
            SpreadsheetCell::Int(value) => println!("Integer: {}", value),
            SpreadsheetCell::Float(value) => println!("Float: {}", value),
            SpreadsheetCell::Text(text) => println!("Text: {}", text),
        }
    }
}

这种方式确保了所有向量中的值都属于同一类型(即枚举类型),同时允许我们存储不同“实际”类型的值,并通过 match 语句在编译时检查每个可能的情况。

7. 向量的内存释放

Rust 中的向量在超出作用域后会自动释放,向量中的所有元素也会随之被 drop(销毁)。这一机制确保了内存的自动回收。

例如:

fn main() {
    {
        let v = vec![1, 2, 3, 4];
        // 在这里 v 以及其中的值都是有效的
        println!("Vector inside scope: {:?}", v);
    } // 离开作用域后,v 自动被 drop,内存被释放

    // 这里 v 不再有效
}

借用检查器同样会确保在向量被 drop 之后,不再存在对其中元素的有效引用。

总结

本文介绍了如何在 Rust 中使用向量来存储值列表,包括以下几个方面:

  • 创建向量:使用 Vec::new 创建空向量或使用 vec! 宏初始化向量,并掌握类型推断与显式注解的区别。
  • 更新向量:通过 push 方法向向量添加元素,理解可变性的重要性。
  • 读取向量元素:比较索引语法和 get 方法的优缺点,特别是处理越界访问时的区别。
  • 遍历向量:演示如何使用 for 循环对向量进行不可变和可变遍历,并说明了使用解引用操作符来修改元素的方式。
  • 存储多种类型:通过定义枚举来将不同类型的值统一存储在一个向量中,并利用 match 语句在编译时进行检查。
  • 向量的释放:说明向量在超出作用域后会自动释放,同时向量中的元素也会被 drop,从而确保内存安全。

向量是 Rust 常用且强大的集合类型,熟练掌握其用法能够帮助你编写出既高效又安全的代码。接下来,你还可以继续探索 Rust 中其他集合类型(如 StringHashMap 等)的使用方式,进一步提升项目的组织和数据处理能力。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 为什么要使用 Rust 语言、Rust 语言有什么优势

    为什么要使用 Rust 语言、Rust 语言有什么优势

    虽然 Rust 是一种通用的多范式语言,但它的目标是 C 和 C++占主导地位的系统编程领域,很多朋友会问rust语言难学吗?rust语言可以做什么,今天带着这些疑问通过本文详细介绍下,感兴趣的朋友一起看看吧
    2022-10-10
  • Rust错误处理之`foo(...)?`的用法与错误类型转换小结

    Rust错误处理之`foo(...)?`的用法与错误类型转换小结

    foo(...)?语法糖为Rust的错误处理提供了极大的便利,通过结合map_err方法和From trait的实现,你可以轻松地处理不同类型的错误,并保持代码的简洁性和可读性,这篇文章主要介绍了Rust错误处理:`foo(...)?`的用法与错误类型转换,需要的朋友可以参考下
    2024-05-05
  • 使用Rust语言搞定图片上传功能的示例详解

    使用Rust语言搞定图片上传功能的示例详解

    这篇文章主要为大家详细介绍了如何使用Rust语言搞定图片上传功能,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2025-08-08
  • 深入了解Rust的生命周期

    深入了解Rust的生命周期

    生命周期指的是引用保持有效的作用域,Rust的每个引用都有自己的生命周期。本文将通过示例和大家详细说说Rust的生命周期,需要的可以参考一下
    2022-12-12
  • Rust中用enum实现多参数Hook机制完整代码

    Rust中用enum实现多参数Hook机制完整代码

    在 Rust 中,如果想为enum实现一个带多参数的 Hook 机制,可以结合模式匹配和枚举来处理,这种方式可以扩展到支持不同类型的输入参数和逻辑处理,下面通过示例代码介绍Rust中用enum实现多参数Hook机制,感兴趣的朋友一起看看吧
    2024-12-12
  • rust 创建多线程web server的详细过程

    rust 创建多线程web server的详细过程

    web server 中主要的两个协议是 http 和 tcp,tcp 是底层协议,http 是构建在 tcp 之上的,本篇文章重点给大家介绍rust 创建多线程web server的详细过程,感兴趣的朋友跟随小编一起看看吧
    2023-11-11
  • Rust异步Web框架Axum的深入原理解析与高级用法

    Rust异步Web框架Axum的深入原理解析与高级用法

    Axum是一个功能强大、简单易用的异步Web框架,基于Tokio异步运行时,具有高度模块化的架构和类型安全的特点,通过本文的介绍,我们学习了Axum框架的架构与核心组件、路由系统、高级功能、性能优化方法、实战项目的应用以及常见问题的解决方案
    2026-03-03
  • Rust中HashMap类型的使用详解

    Rust中HashMap类型的使用详解

    Rust中一种常见的集合类型是哈希映射,本文主要介绍了Rust中HashMap类型的使用详解,包含创建访问修改遍历等,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • 如何使用Rust直接编译单个的Solidity合约

    如何使用Rust直接编译单个的Solidity合约

    本文介绍了如何使用Rust语言直接编译Solidity智能合约,特别适用于没有外部依赖或flatten后的合约,一般情况下,Solidity开发者使用Hardhat或Foundry框架,本文给大家介绍如何使用Rust直接编译单个的Solidity合约,感兴趣的朋友一起看看吧
    2024-09-09
  • 使用 Rust 实现的基础的List 和 Watch 机制示例流程

    使用 Rust 实现的基础的List 和 Watch 机制示例流程

    本文给大家介绍使用Rust实现的基础的List和Watch机制示例流程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-09-09

最新评论