這一篇博客我們來(lái)聊一下Rust中 vector 的使用。vector 就像數(shù)組一樣,用于存儲(chǔ)同一類型的一系列的值,但是允許動(dòng)態(tài)地添加和刪除值,以及擁有一些其他的方法。
vector 的定義
在代碼中,使用 Vec<T> 來(lái)定義一個(gè) vector 類型的變量
fn main() {
// 這一個(gè)可以動(dòng)態(tài)添加和刪除元素
let mut vec1: Vec<u32> = Vec::new();
// 在定義的時(shí)候就填充好值,因?yàn)闆](méi)有mut,所以無(wú)法動(dòng)態(tài)添加和刪除
let vec2 = vec![1, 2, 3, 4, 5];
let vec3 = vec!["str1", "str2", "str3"];
}
vec!是rust提供的宏,可以動(dòng)態(tài)地根據(jù)我們的數(shù)據(jù),自動(dòng)推斷出這個(gè) vector 變量的類型
添加和刪除元素
向 vector 中添加元素,使用 push 方法,從vector中刪除最后添加的元素,使用 pop 方法
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(10);
nums.push(11);
nums.push(12);
println!("{:?}", nums); // 打印出 [10, 11, 12]
nums.pop(); // 將最后的元素拿出來(lái)丟了
println!("{:?}", nums); // 這里打印出 [10, 11]
}
pop會(huì)將值返回,返回的類型是Option<T>類型,我們可以定義一個(gè)變量接收 pop 出來(lái)的值
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(10);
nums.push(11);
nums.push(12);
println!("{:?}", nums);
let x = nums.pop();
println!("x: {:?}", x); // 這里將打印出 Some(12)
}
如果 vector 中已經(jīng)沒(méi)有元素,繼續(xù)使用
pop,將返回Option<T>中的None
訪問(wèn)特定所以呢的元素
就像數(shù)組一樣,vector也可以使用 [index] 這樣的形式去訪問(wèn)某個(gè)元素,還可以使用 get(index) 方法訪問(wèn)。
fn main() {
let mut nums: Vec<u32> = Vec::new();
nums.push(10);
nums.push(11);
nums.push(12);
// 這里獲取的是第0個(gè)元素的引用
let first_num = &nums[0];
println!("first_num: {}", first_num);
// get 方法在這里返回的 Option<&u32>
let second_num = nums.get(1);
println!("x:{:?}", second_num);
}
如果我們嘗試訪問(wèn)越界索引的元素會(huì)怎樣呢?如果使用
[index]這種形式,Rust 會(huì)直接導(dǎo)致 panic 然后退出進(jìn)程,如果使用get(index)這種形式,Rust會(huì)返回Option<T>中的None
為什么這里獲取值的時(shí)候,要獲取它引用,而不是值本身呢?對(duì)于 copy 類型的數(shù)據(jù),似乎沒(méi)有什么區(qū)別,但是對(duì)于 String 這樣類型的數(shù)據(jù),如果我們直接獲取值,就會(huì)導(dǎo)致所有權(quán)的移動(dòng)??聪旅娴谋闅v代碼
遍歷 vector
fn main() {
let mut names: Vec<String> = Vec::new();
names.push("Jack".to_string());
names.push("Tony".to_string());
names.push("Tina".to_string());
// 遍歷vector中每一個(gè)元素,然后打印出來(lái)
for name in &names {
println!("name: {}", name);
}
// 打印出整個(gè)vector來(lái)
println!("names: {:?}", names);
}
上面的代碼,如果我們把第7行改為 for name in names 那么這段代碼就會(huì)編譯不過(guò),因?yàn)?vector 中的值的所有權(quán),已經(jīng)移動(dòng)到了 println 中的 name 變量,所以在第12行再次訪問(wèn)的時(shí)候,就會(huì)出錯(cuò),所以編譯器會(huì)直接編譯不過(guò)。所以,在獲取和遍歷 vector 中值的時(shí)候,一定要注意所有權(quán)轉(zhuǎn)移的問(wèn)題
在 vector 中存儲(chǔ)不同類型的值
在博客開(kāi)始的時(shí)候我們說(shuō) vector 只能存儲(chǔ)相同類型的值,這是沒(méi)錯(cuò)的。這里我們存儲(chǔ)不同類型的值,是使用了上一篇講到的枚舉類型而做到的??聪旅娴拇a
#[derive(Debug)]
enum Data {
IData(i32),
FData(f32),
SData(String),
}
fn main() {
let mut data_sets: Vec<Data> = Vec::new();
data_sets.push(Data::IData(10));
data_sets.push(Data::FData(3.14159));
data_sets.push(Data::SData(String::from("Hello Rust"));
}
先定義一個(gè)擁有多種數(shù)據(jù)類型的枚舉,然后定義一個(gè)存儲(chǔ)這種枚舉類型的 vector,這樣就實(shí)現(xiàn)了一個(gè) vector 中存儲(chǔ)不同類型的數(shù)據(jù)。