读到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()
尝试获取一个可变引用,显然触发了规则发生了错误
网友评论