【问题标题】:How does the borrow checker deal with a reference returned from a function? [duplicate]借用检查器如何处理从函数返回的引用? [复制]
【发布时间】:2019-12-03 20:43:53
【问题描述】:

我是 Rust 的新手,我正在阅读 The Rust Programming Language 在线书籍。我现在遇到一个关于 Rust 借用检查的问题,代码示例如下所示:

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    for (i, &b) in bytes.iter().enumerate() {
        if b == b' ' {
            return &s[..i];
        }
    }

    &s[..]
}

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

    let word = first_word(&s);
    s.clear();

    println!("word = {}", word);
}

Rust 编译器通过以下错误消息抱怨代码:

error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
  --> src/main.rs:16:5
   |
15 |     let word = first_word(&s);
   |                           -- immutable borrow occurs here
16 |     s.clear();
   |     ^^^^^^^^^ mutable borrow occurs here
17 | 
18 |     println!("word = {}", word);
   |                           ---- immutable borrow later used here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0502`.
error: Could not compile `demo`.

To learn more, run the command again with --verbose.

在线书籍解释说,在执行s.clear() 时,会创建一个对s 的新可变引用,并与现有的不可变引用word 冲突,因为word 直到最后一个println! 才超出其范围陈述。似乎不知何故,Rust 的借用检查器发现 word(由 first_word 函数返回)指的是 s。它是如何实现的?

【问题讨论】:

  • @DenysSéguret:我猜这本书没有更新。
  • 这在本书的Validating References with Lifetimes小节中有详细说明。我建议跳到该部分以了解 Rust 中的生命周期是如何工作的。
  • 感谢您的回复。我只是尝试修改代码以直接从 first_word 函数返回字符串文字,并且抱怨仍然存在。看来借用检查器是根据您刚才提到的生命周期做出决定的。我会读一下,谢谢。
  • @Lancern 借用检查器仅查看函数原型(即参数和返回类型)来确定输入和输出引用之间的关系。更改函数的实现不会改变函数在调用站点的处理方式。
  • 为了返回引用,您必须将该引用与输入之一相关联。然后调用者可以负责提供一个足够长的输入以使用返回的引用。您根本无法返回任意引用;为了返回未连接到输入的内容,您必须返回(拥有的)项目而不是参考。

标签: rust


【解决方案1】:

当你有

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

真的是这样

fn first_word<'a>(s: &'a String) -> &'a str {

(见lifetime elision)。

也就是说,输出的生命周期就是输入的生命周期。

这就是借用检查器如何推断word(由first_word 函数返回)引用s

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 2016-01-04
    • 2015-07-28
    相关资源
    最近更新 更多