我正在学习 RustRust 编程语言本书可从 No Starch Press 购买但遇到了一个问题,编译器的行为与书中第 4 章第 4 页中所解释的不同。 77.
本书的第 4 章讨论了所有权,以及第 4 页的示例。 77 与此类似,没有最后的println!()
in main()
(我还添加了第 76 页中的注释和函数来创建 MCVE)。我还创建了一个游乐场.
fn main() {
let mut s = String::from("Hello world!");
let word = first_word(&s);
// according to book, compiler should not allow this mutable borrow
// since I'm already borrowing as immutable, but it does allow it
s.clear();
// but of course I do get error here about immutable borrow later being
// used here, but shouldn't it have errored on the clear() operation before
// it got here?
println!("First word of s is \"{}\"", word);
}
// return string slice reference to first word in string or entire string if
// no space found
fn first_word(s: &String) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[..i];
}
}
&s[..]
}
我明白为什么编译器会在当前的位置抛出错误。但我从书中的理解是should当我尝试清除字符串时导致编译器错误,因为我无法借用s
是可变的,因为它也被借用为不可变的,从而消除了我收到的错误的可能性(即,它不应该编译即使没有我的决赛println!()
)。但只要我不尝试使用引用,它对我来说编译得很好word
之后clear()
手术。
本书使用 Rust 1.21.0 (seep。 2) 而我使用的是 Rust 1.31.0——所以这可能是编译器引入的一个变化,但我试图理解why。为什么像现在这样犯错误比书中说会犯错误更好?
需要明确的是,我理解这些错误本身。我试图理解为什么它不会在书中所说的位置抛出编译器错误(即为什么编译器行为发生变化?)。
这是由于以下原因而发生的变化非词汇生命周期,最新版本 Rust 中所做的更新(如果我没记错的话,在 Rust 1.31 中引入的 2018 版本中已稳定)。
在 Rust 的早期版本(包括本书所基于的版本)中,任何引用都应该在其创建的整个范围内都有效(即,直到大括号末尾)。如果您使用删除该行word
并尝试在旧版本上编译代码,它会发出相同的错误 - “借用为可变,而借用为不可变”。
现在,借用检查器跟踪该引用是否被真正使用。如果你没有使用word
after s.clear()
,假设对的不可变引用s
可以在之前安全地丢弃s.clear()
采用可变的,因此,正如您所提到的,该代码将被安全地编译。当。。。的时候println!
在那里,借用检查器会看到不可变和可变借用的作用域是相交的,并准确地告诉您这一点 - 请注意,错误分为三个部分:
- 不可变借用的开始,
- 可变借用的开始,
- 不可变借用的使用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)