为什么这不算作一成不变的借贷?

Dar*_*ikh 3 rust

我正在阅读官方的Rust Book,并在4.3节中查看清单4-8。

代码如下:

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);

    s.clear();
}
Run Code Online (Sandbox Code Playgroud)

这行:

let word = first_word(&s);
Run Code Online (Sandbox Code Playgroud)

似乎借用了一成不变的提法s。(这是我想我错了的地方;我只是不知道为什么。)

在下一行,我们s通过调用clear()方法来进行变异。

我期望编译器抛出:

cannot borrow `s` as mutable because it is also borrowed as immutable
Run Code Online (Sandbox Code Playgroud)

为什么会编译?

Vit*_*meo 5

s对的调用过程中,该字符串不变地借用了first_word。一旦将控件返回到mainafter first_word,就不再认为该字符串是借来的,并且可以按照您所观察到的进行更改。


如果first_word返回a &String,则通过将其分配给变量来延长了其寿命,那么您将看到预期的错误。例如

fn first_word(s: &String) -> &String {
    &s
}

fn main() {
    let mut s = String::from("hello world");
    let word = first_word(&s);
    s.clear();
}
Run Code Online (Sandbox Code Playgroud)

不能借来s可变,因为它也借来不可变

https://rust.godbolt.org/z/cMVdVf

在这种情况下,添加一个额外的作用域将解决此问题:

fn main() {
    let mut s = String::from("hello world");

    {
        let word = first_word(&s);
    }

    s.clear();
}
Run Code Online (Sandbox Code Playgroud)