rust编译器如何生成;不可变借阅发生在此处;?
我正在学习Rust,下面的代码来自在线书籍《Rust编程语言》: 编译程序如下所示:rust编译器如何生成;不可变借阅发生在此处;?,rust,Rust,我正在学习Rust,下面的代码来自在线书籍《Rust编程语言》: 编译程序如下所示: |让单词=第一个单词(&s); |--此处发生不可变借用 所以我认为“不可变借用发生在这里”指的是&s,而不是“let word”。 但如果我改变 let word = first_word(&s); 到 编译器错误消失。 所以我觉得“不可变借用发生在这里”是指“let word”,而不是&s 如果第一个单词的返回值仅取决于另一个字符串(这意味着第一个单词根本不取决于&s),如下所示: fn fir
|让单词=第一个单词(&s);
|--此处发生不可变借用
所以我认为“不可变借用发生在这里”指的是&s
,而不是“let word”。
但如果我改变
let word = first_word(&s);
到
编译器错误消失。
所以我觉得“不可变借用发生在这里”是指“let word”,而不是&s
如果第一个单词
的返回值仅取决于另一个字符串(这意味着第一个单词
根本不取决于&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[..]
}
编译器仍然说:
|让单词=第一个单词(&s);
|--此处发生不可变借用
我对编译器生成“此处发生不可变借用”的实际操作感到非常困惑。您应该阅读完整错误:
error[E0502]:不能将's'作为可变项借用,因为它也是作为不可变项借用的
-->src/main.rs:18:5
|
16 | let word=第一个单词(&s);
|--此处发生不可变借用
17 |
18 | s.clear();//错误!
|^^^^^^^^^^^^此处发生可变借用
19 |
20 | println!(“第一个字是:{}”,字);
|----此处稍后使用的不可变借用
“不能将s
借用为可变的,因为它也被借用为不可变的”是错误消息,其他所有内容都只是为了指出冲突借用发生的位置
如果第一个单词的返回值只依赖于另一个字符串(这意味着第一个单词根本不依赖于&s),如下所示 这是不对的。函数签名决定了生命周期。在编辑的
第一个单词中
,即使返回从静态字符串借用的str
,实际签名(不省略寿命)如下所示
fn first_word<'a>(s: &'a String) -> &'a str {
...
fn第一个单词和一个str{
...
返回的
&str
绑定到s
的生存期,而不管它来自何处。此示例仅显示如何缩短具有静态生存期的引用。由于返回值绑定到s
的生存期,因此s
被认为是由word
借用的,这是否意味着回答您的问题?暂时忽略错误消息的实际内容,只关注“错误”/“无错误”。您是否理解为什么第一个代码段是错误的(错误),但如果您将let word=first_word(&s);
更改为justfirst_word(&s)
,它将变为正确的(无错误)?我完全想了解借阅检查者是如何得出结论的;但是,如果你不明白它试图保护你免受什么伤害,那么这个过程看起来就像是一堆武断的胡言乱语。(老实说,有时它还是会的。)你可以通过简单地假设借阅检查器拥有完美的信息并且总是正确的,然后尝试从这一点反向工作,看看你的代码是如何违反规则而导致未定义的行为。这种假设不是完全正确的,因为有些事情借阅检查器不理解是可以的,但是is case不是其中之一;例如,在s.clear()
之后使用word
确实会导致UB。Nit:第一个单词的生命周期同时表示,输出只有在s
有效时才有效,而且s
被借用的时间与输出的寿命一样长。这就是为什么要删除word
“修复”问题:第一个单词的结果立即被回收,因此借阅立即结束,可以创建新的借阅。
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[..]
}
fn first_word<'a>(s: &'a String) -> &'a str {
...