切片(Slice)是對(duì)數(shù)據(jù)值的部分引用。
切片這個(gè)名字往往出現(xiàn)在生物課上,我們做樣本玻片的時(shí)候要從生物體上獲取切片,以供在顯微鏡上觀察。在 Rust 中,切片的意思大致也是這樣,只不過(guò)它從數(shù)據(jù)取材引用。
最簡(jiǎn)單、最常用的數(shù)據(jù)切片類(lèi)型是字符串切片(String Slice)。
fn main() { let s = String::from("broadcast"); let part1 = &s[0..5]; let part2 = &s[5..9]; println!("{}={}+{}", s, part1, part2); }
運(yùn)行結(jié)果:
broadcast=broad+cast
上圖解釋了字符串切片的原理(注:Rust 中的字符串類(lèi)型實(shí)質(zhì)上記錄了字符在內(nèi)存中的起始位置和其長(zhǎng)度,我們暫時(shí)了解到這一點(diǎn))。
使用 .. 表示范圍的語(yǔ)法在循環(huán)章節(jié)中出現(xiàn)過(guò)。x..y 表示 [x, y) 的數(shù)學(xué)含義。.. 兩邊可以沒(méi)有運(yùn)算數(shù):
..y 等價(jià)于 0..y x.. 等價(jià)于位置 x 到數(shù)據(jù)結(jié)束 .. 等價(jià)于位置 0 到結(jié)束
注意:到目前為止,盡量不要在字符串中使用非英文字符,因?yàn)榫幋a的問(wèn)題。具體原因會(huì)在"字符串"章節(jié)敘述。
被切片引用的字符串禁止更改其值:
fn main() { let mut s = String::from("nhooo"); let slice = &s[0..3]; s.push_str("yes!"); // 錯(cuò)誤 println!("slice = {}", slice); }
這段程序不正確。
s 被部分引用,禁止更改其值。
實(shí)際上,到目前為止你一定疑惑為什么每一次使用字符串都要這樣寫(xiě)String::from("nhooo") ,直接寫(xiě) "nhooo" 不行嗎?
事已至此我們必須分辨這兩者概念的區(qū)別了。在 Rust 中有兩種常用的字符串類(lèi)型:str 和 String。str 是 Rust 核心語(yǔ)言類(lèi)型,就是本章一直在講的字符串切片(String Slice),常常以引用的形式出現(xiàn)(&str)。
凡是用雙引號(hào)包括的字符串常量整體的類(lèi)型性質(zhì)都是 &str:
let s = "hello";
這里的 s 就是一個(gè) &str 類(lèi)型的變量。
String 類(lèi)型是 Rust 標(biāo)準(zhǔn)公共庫(kù)提供的一種數(shù)據(jù)類(lèi)型,它的功能更完善——它支持字符串的追加、清空等實(shí)用的操作。String 和 str 除了同樣擁有一個(gè)字符開(kāi)始位置屬性和一個(gè)字符串長(zhǎng)度屬性以外還有一個(gè)容量(capacity)屬性。
String 和 str 都支持切片,切片的結(jié)果是 &str 類(lèi)型的數(shù)據(jù)。
注意:切片結(jié)果必須是引用類(lèi)型,但開(kāi)發(fā)者必須自己明示這一點(diǎn):
let slice = &s[0..3];
有一個(gè)快速的辦法可以將 String 轉(zhuǎn)換成 &str:
let s1 = String::from("hello"); let s2 = &s1[..];
除了字符串以外,其他一些線性數(shù)據(jù)結(jié)構(gòu)也支持切片操作,例如數(shù)組:
fn main() { let arr = [1, 3, 5, 7, 9]; let part = &arr[0..3]; for i in part.iter() { println!("{}", i); } }
運(yùn)行結(jié)果:
1 3 5