【发布时间】:2020-10-19 10:50:47
【问题描述】:
我正在学习 Rust,以下代码来自在线书籍 The Rust Programming Language link:
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);
}
编译器如下:
| let word = first_word(&s);
| -- immutable borrow occurs here
所以我认为“这里发生不可变借用”是在谈论 &s 而不是“让单词”。
但是如果我改变了
let word = first_word(&s);
到
first_word(&s);
编译器错误消失。
所以这让我觉得“这里发生不可变借用”是在谈论“让单词”而不是&s。
如果first_word的返回值只依赖于另一个字符串(这意味着first_word根本不依赖于&s)如下:
fn first_word(s: &String) -> &str {
println!("the input for first word is: {}", s);
let s1 = "hi rust";
let bytes = s1.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s1[0..i];
}
}
&s1[..]
}
编译器仍然在下面说:
| let word = first_word(&s);
| -- immutable borrow occurs here
我对编译器实际上为生成“此处发生不可变借用”所做的工作感到非常困惑。
【问题讨论】:
-
暂时忽略错误消息的实际内容,只关注“错误”/“无错误”。你明白为什么第一个 sn-p 是错误的(错误),但是如果你将
let word = first_word(&s);更改为只是first_word(&s);,它就会变得正确(没有错误)?我完全渴望了解借用检查器如何得出结论;但是,如果您不了解它试图保护您免受什么侵害,那么该过程将看起来像很多武断的 gobbledygook。 (老实说,有时确实如此。) -
你可以通过简单地假设借用检查器具有完美的信息并且总是正确的,并尝试从它向后工作以查看你的代码如何违反规则以导致未定义的行为,从而在 Rust 中走得更远。这个假设并不完全正确,因为借用检查器不理解的一些事情是可以的,但 this 案例不是其中之一;即,在
s.clear()之后使用word确实会在此处导致UB。
标签: rust