讀到4.3節的時候有點迷糊,所以記錄一下問題
1. 梳理下文章邏輯
- 首先由一個例子引出一個問題
// 具體邏輯不用管 就是返回第一個單詞的長度
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
// 如果這樣使用就會有問題
fn main() {
let mut s = String::from("hello world");
let word = first_word(&s); // word 的值為 5
s.clear(); // 這清空了字符串,使其等于 ""
// word 在此處的值仍然是 5,
// 但是沒有更多的字符串讓我們可以有效地應用數值 5。word 的值現在完全無效!
}
問題就是:s.clear
之后word
的值依然是5,如果你仍然對s
使用word
肯定會產生錯誤。其實關鍵不是這個錯誤,是編譯器沒有任何報錯,你不能發現錯誤(雖然這個例子并沒有展示出這個錯誤的嚴重性)
- 為了使編譯器能發現錯誤,引出了
slice
slice
的用法就不贅述了,注意和js
的slice
的區別
// js中的slice
const a = [1, 2, 3]
const b = a.slice(0)
// a和b沒有任何關聯 操作a不會影響b 相當于深拷貝
//=> 而rust的slice 返回的只是指定位置開始的指針 數據地址還是和原數據一樣的
- 為了解決問題 改進了代碼
// 這里直接返回了s的slice
fn first_word(s: &String) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
// 使用的時候 編譯器會報錯
fn main() {
let mut s = String::from("hello world");
let word = first_word(&s);
s.clear(); // error!
println!("the first word is: {}", word);
}
報錯的原因需要結合4.2
節,一個作用域里面不能同時出現可變引用
和不可變引用
。這里返回了一個slice
不可邊引用,而s.clear()
嘗試獲取一個可變引用,顯然觸發了規則發生了錯誤