文章目录
常见容器
这部分主要介绍Rust中的向量Vec<T>
、字符串和哈希表。
向量Vec<T>
向量和数组的最大区别在于,数组的长度必须在编译时确定,而且之后长度不能更改,所以数组使用的是栈内存,而向量的长度是动态的,可以在运行时增加或减少,因此使用的是堆内存。
创建向量
fn main() {
let vec: Vec<i32> = Vec::new();
}
这种创建方式必须指定向量类型。
fn main() {
let vec = vec![1, 2, 3];
let vec = vec![0; 5]; // [0, 0, 0, 0, 0]
}
这种创建方式可以根据数据自动推断出向量类型。
添加元素
fn main() {
let vec: Vec<i32> = Vec::new();
vec.push(0);
}
读取元素
直接利用索引读取,如下:
fn main() {
let vec = vec![1, 2, 3, 4];
println!("{}", vec[3]);
}
当访问越界时,比如vec[4]
,在运行时会panic
。也可以使用get
方法读取,它返回的是Option<T>
类型,如果访问越界,返回的是None
,否则返回的是Some
,因此需要结合match {}
进行处理。
fn main() {
let vec = vec![1, 2, 3, 4];
let index = 4;
match vec.get(index) {
Some(v) => println!("{}", v),
None => println!("None"),
}
}
向量元素的引用和向量的引用
Vec<T>
的push
方法需要修改向量,因此push
方法的参数是&mut self
,如果获得了向量中元素的引用,那么就不再允许调用push
方法,因为会违背引用的规则:任意时刻只能存在一个可变引用或者多个不可变引用。
fn main() {
let mut vec = vec![1, 2, 3, 4];
let ele = &vec[3];
vec.push(5);
}
// 报错信息
// 3 | let ele = &vec[3];
// | --- immutable borrow occurs here
// 4 | vec.push(5);
// | ^^^^^^^^^^^ mutable borrow occurs here
// 5 | println!("{}", ele);
// | --- immutable borrow later used here
如果向量中的元素没有实现Copy
特性,比如Vec<String>
,那么let x = vec[0];
会移动向量中元素的所有权,导致移动后vec[0]
就会不存在,而Rust不允许这种情况出现,如下:
fn main() {
let vec = vec![String::from("hello"), String::from("world")];
let x = vec[0];
}
// 报错信息
// 3 | let x = vec[0];
// | ^^^^^^
// | |
// | move occurs because value has type `String`, which does not implement the `Copy` trait
// | help: consider borrowing here: `&vec[0]`
如提示,可以通过引用访问元素,let x = &vec[0];
,也可以通过get
方法访问元素,这种情况下,返回的是引用,如下:
fn main() {
let vec = vec![String::from("hello"), String::from("world")];
let x = vec.get(0); // x是&String类型
}
删除向量
当向量离开作用域后,会调用drop
方法释放向量占用的资源,同时,向量中的元素也会调用drop
方法释放资源。
使用迭代器访问元素
如果不改变向量中的元素,如下:
fn main() {
let vec = vec![1, 2, 3, 4];
for