Rust语言

关注公众号 jb51net

关闭
首页 > 软件编程 > Rust语言 > Rust vector

Rust中vector的详细用法

作者:ftzchina

Rust和C++同样也有vector概念,本文主要介绍了Rust中vector的详细用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

用过C++的相信对vector概念不陌生了,C++中我们称vector为容器,它能够像容器一样存放各种类型的对象。Rust中同样也有vector概念,在Rust中vector 允许我们在一个单独的数据结构中储存多个值,所有值在内存中彼此相邻排列,在内存中的存储形式和数组一样,vector 只能储存相同类型的值。但是借助另一种结构(枚举),我们可以用vector存储不同类型的值,当然这是包了一层,下面我们讲一下Rust的vector详细用法。

一:vector的实例创建

fn main() {
    let vec_ins:Vec<u32> = Vec::new();
}

上面我们通过Vec的new函数创建了一个vector实例,并指定了其里面存储的值是u32类型,那我们用new创建的时候能不能不指定值类型呢。

这是不允许的,如果用new创建的时候不指定类型,那么因为没有向这个 vector 中插入任何值,Rust 并不知道我们想要储存什么类型的元素。这一点非常重要。vector 是用泛型实现的,第 10 章会涉及到如何对你自己的类型使用它们。现在,我们知道 Vec 是一个由标准库提供的类型,它可以存放任何类型,而当 Vec 存放某个特定类型时,那个类型位于尖括号中。        

那假如我在创建的同时,传入vector的元素,是不是就意味着不用显示的指定类型。

fn main() {
    let vec_ins = vec![1, 2, 3];
    println!("vec is {:?}",vec_ins); 
}

运行结果:

PS F:\skillup\rust\hello_world\greeting> cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target\debug\greeting.exe`
vec is [1, 2, 3]

vector创建的同时传入了元素,Rust 就可以根据插入的元素推断出存放的类型。更常见的做法是使用初始值来创建一个 Vec,而且为了方便 Rust 提供了 vec! 宏。这个宏会根据我们提供的值来创建一个新的 Vec。

二:vector的元素插入

我们创建了vector,那么如何向vector中插入元素。

fn main() {
    let mut vec_ins:Vec<char> = Vec::new();
    vec_ins.push('f');
    vec_ins.push('t');
    vec_ins.push('z');
    println!("vec is {:?}",vec_ins); 
}

运行结果:

PS F:\skillup\rust\hello_world\greeting> cargo run
   Compiling greeting v0.1.0 (F:\skillup\rust\hello_world\greeting)
    Finished dev [unoptimized + debuginfo] target(s) in 1.19s
     Running `target\debug\greeting.exe`
vec is ['f', 't', 'z']

Rust中可以使用 push 方法往vector中插入元素

三:vector的元素读取

在Rust中我们有两种方法来获取vector中元素的值,一是通过索引,二是通过get方法。下面我们来看一个具体的例子

fn main() {
    let mut vec_ins:Vec<char> = Vec::new();
    vec_ins.push('f');
    vec_ins.push('t');
    vec_ins.push('z');
    println!("vec is {:?}",vec_ins); 

    let second_ele= vec_ins[1];
    println!("the second element is {}",second_ele); 

    match vec_ins.get(1) {
        Some(second_ele) => println!("The second element is {}", second_ele),
        None => println!("There is no second element."),
    }
}

运行结果:

S F:\skillup\rust\hello_world\greeting> cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target\debug\greeting.exe`
vec is ['f', 't', 'z']
the second element is t
The second element is t

Rust 有两个引用元素的方法的原因是程序可以选择如何处理当索引值在 vector 中没有对应值的情况。

当引用一个不存在的元素时 Rust 会造成 panic。这个方法更适合当程序认为尝试访问超过 vector 结尾的元素是一个严重错误的情况,这时应该使程序崩溃。比如vector总共有5个元素,你用下标去获取第6个元素,就是越界访问,这时候程序就panic了,当 get 方法被传递了一个数组外的索引时,它不会 panic 而是返回 None。当偶尔出现超过 vector 范围的访问属于正常情况的时候可以考虑使用它。接着你的代码可以有处理 Some(&element) 或 None 的逻辑。例如,索引可能来源于用户输入的数字。如果它们不慎输入了一个过大的数字那么程序就会得到 None 值,你可以告诉用户当前 vector 元素的数量并再请求它们输入一个有效的值。这就比因为输入错误而使程序崩溃要友好的多!

一旦程序获取了一个有效的引用,借用检查器将会执行所有权和借用规则来确保 vector 内容的这个引用和任何其他引用保持有效。不能在相同作用域中同时存在可变和不可变引用的规则。当我们获取了 vector 的第一个元素的不可变引用并尝试在 vector 末尾增加一个元素的时候,这是行不通的:

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

    let first = &v[0];

    v.push(6);

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

为什么第一个元素的引用会关心 vector 结尾的变化?不能这么做的原因是由于 vector 的工作方式:在 vector 的结尾增加新元素时,在没有足够空间将所有所有元素依次相邻存放的情况下,可能会要求分配新内存并将老的元素拷贝到新的空间中。这时,第一个元素的引用就指向了被释放的内存。借用规则阻止程序陷入这种状况。

四:vector的元素遍历

 我们可以用for循环来遍历vector元素

fn main() {
    let mut vec_ins:Vec<char> = Vec::new();
    vec_ins.push('f');
    vec_ins.push('t');
    vec_ins.push('z');
    println!("vec is {:?}",vec_ins); 

    for i in &vec_ins{
        println!("the element is {}",i);
    }
}

运行结果:

vec is ['f', 't', 'z']
the element is f
the element is t
the element is z

那么我们能不能遍历的同时改变vector元素的值呢

fn main() {
    let mut vec_ins:Vec<char> = Vec::new();
    vec_ins.push('f');
    vec_ins.push('t');
    vec_ins.push('z');
    println!("vec is {:?}",vec_ins); 

    for i in &mut vec_ins{
        *i = 'x'
    }
    println!("the element is {:?}",vec_ins);
}

运行结果:

vec is ['f', 't', 'z']
the element is ['x', 'x', 'x']

为了修改可变引用所指向的值,在使用 = 运算符之前必须使用解引用运算符(*)获取 i 中的值

五:vector借助枚举来存储不同类型的值

上面讲到vector 只能储存相同类型的值。如果有这个限制vector说实话和数组功能就相差无几了。何谓道高一尺,魔高一丈,很幸运的是vector绝对有能力做到存储不同类型的值,不过要借助另外一个结构,枚举的成员都被定义为相同的枚举类型,所以当需要在 vector 中储存不同类型值时,我们可以定义并使用一个枚举!

#[derive(Debug)]
enum Student {
    Age(i32),
    Sex(char),
    Name(String),
}
fn main() {
    let student = vec![
        Student::Age(18),
        Student::Sex('男'),
        Student::Name(String::from("ftz"))
    ];
    println!("The student is {:?}",student);
}

上面我们借助枚举来存储一个学生的信息,包括年龄,性别,名字,对应三种不同的数据类型。

六:vector学习总结

Rust 在编译时就必须准确的知道 vector 中类型的原因在于它需要知道储存每个元素到底需要多少内存。第二个好处是可以准确的知道这个 vector 中允许什么类型。如果 Rust 允许 vector 存放任意类型,那么当对 vector 元素执行操作时一个或多个类型的值就有可能会造成错误。使用枚举外加 match 意味着 Rust 能在编译时就保证总是会处理所有可能的情况。

到此这篇关于Rust中vector的详细用法的文章就介绍到这了,更多相关Rust vector内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文