这个语句结束时,临时值将被释放。

35

我正在尝试使用Select crate来抓取一个网页:

let document = Document::from_read(response).unwrap();

for node in document.find(Class("lia-list-row")) {
    let title = node.find(Class("page-link")).next().unwrap();
    let title_text = title.text().trim();

    println!("{}\n", title_text);
}

导致以下错误:

let title_text = title.text().trim();
                 ^^^^^^^^^^^^       - temporary value is freed at the end of this statement
                 |
                 creates a temporary which is freed while still in use

println!("{} - {}\n", i, title_text);
                         ---------- borrow used here, in later iteration of loop

我通过分离.text().trim()来解决了它。

let title_text = title.text();
let trim_text = title_text.trim();

有什么区别?为什么第一次尝试失败了?


请查看如何创建一个[MCVE],然后[编辑]您的问题以包含它。我们无法确定代码中存在哪些crate、type、trait、field等。尝试在Rust Playground上生成能够重现您的错误的内容,或者您可以在全新的Cargo项目中重现它。还有Rust特定的MCVE提示 - Shepmaster
1个回答

58

起初看起来似乎有些复杂,但请记住String&str是不同的东西。

String可以独立存在并被使用,但&str只是指向String的一部分的引用。因此,只要被引用的String存在,&str就可以存在。现在我们来看看它在返回签名中应该如何工作。

let title_text = title   .text()   .trim();
//               ^       ^         ^
//               Node    String <- &str
  1. title是一个select::Node

  2. Node::text返回一个String,但没有将其与上下文绑定。

  3. 反过来,String::trim返回一个&str,它是对String本身的一部分的引用。

最终,借用检查器只是不理解它应该如何处理对String的引用,因为它是一个临时值(非绑定),不能在上下文中存活足够长的时间。


7
有没有不声明新变量就能解决这个问题的方法? - rm.rf.etc
14
如果你可以接受复制的话,你可以使用title.text().trim().to_string() - bohdan_trotsenko
这里我们通常使用 let text = &title.text().trim().to_owned() 吗?以避免复制并延长引用的生命周期? - mathtick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接