错误 [E0716]:借用时临时值下降(生锈)

Jam*_*979 3 rust

tl;drerror[E0716]: temporary value dropped while borrowed是一个困难且常见的问题,有一致的解决方案吗?


我遇到了困难的 rustc 错误

error[E0716]: temporary value dropped while borrowed
...

creates a temporary which is freed while still in use
Run Code Online (Sandbox Code Playgroud)

搜索Stackoverflow,有很多关于这个rust error的问题error[E0716]也许 Rust 专家可以为这个常见的新手问题提供一个通用的解决方案,一个足够好的解决方案,它也可以回答链接的问题(见下文)。

示例代码

一个简洁的代码示例来演示该问题(Rust Playground):

type Vec1<'a> = Vec::<&'a String>;

fn fun1(s1: &String, v1: &mut Vec1) {
    v1.insert(0, &s1.clone());
}

fn main() {
    let mut vec1 = Vec::new();
    let str1 = String::new();
    fun1(&str1, &mut vec1);
}
Run Code Online (Sandbox Code Playgroud)

结果:

error[E0716]: temporary value dropped while borrowed
 --> src/main.rs:4:19
  |
3 | fn fun1(s1: &String, v1: &mut Vec1) {
  |                      -- has type `&mut Vec<&'1 String>`
4 |     v1.insert(0, &s1.clone());
  |     --------------^^^^^^^^^^-- temporary value is freed at the end of this statement
  |     |             |
  |     |             creates a temporary which is freed while still in use
  |     argument requires that borrow lasts for `'1`

For more information about this error, try `rustc --explain E0716`.
Run Code Online (Sandbox Code Playgroud)

我的理解

我的理解是v1.insert(0, &s1.clone());
会使用堆作为存储s1.clone()来创建一个新的。String然后,新克隆的String(添加的&)引用被传递给 call v1.insert。因此,新String数据和传递给的引用insert将在函数fun1返回后保留。

但 Rust 编译器报告s1.clone()只是暂时的。

类似的链接问题

以下是类似问题的链接,该问题的版本并不总是相同,但有些更麻烦和冗长(IMO)。

我对链接到该问题的这些问题添加了评论。

Ale*_*nta 5

你的问题确实是在编译指示的行上。我们稍微分析一下:

fn fun1(s1: &String, v1: &mut Vec1) {
    v1.insert(0, &s1.clone());
}
Run Code Online (Sandbox Code Playgroud)

你的理解不太正确。让我们看看插入的签名:

pub fn insert(&mut self, index: usize, element: T)
Run Code Online (Sandbox Code Playgroud)

类型T意味着它按值捕获,因此调用后不会使用元素。您只需通过将向量设置为Vec<&String>而不是Vec<String>来对此进行调整。

结果:您想要插入对字符串克隆的引用

操作方法:克隆并插入引用

rust 的引用和 C/C++ 指针之间的区别在于,rust 不允许引用指向已释放的数据(它们必须始终指向有效数据)。当您克隆字符串时,您会创建它的副本,但该副本仅在fun1的生命周期内可用。当对fun1 的调用结束时,克隆的字符串将被删除,因为该函数拥有该克隆,因此它负责清理它(rust 的基于所有权的资源管理)。

在 C++ 中,这是有效的:您可以分配一个指针并将该指针推入向量中,但 Rust 不允许这样的事情。

你的fun1相当于这个:

fn fun1(s1: &String, v1: &mut Vec1) {
    let im_tmp = s1.clone();
    v1.insert(0, &im_tmp);
}
Run Code Online (Sandbox Code Playgroud)

类似的操作应该始终敲响警钟,因为im_tmp将被清除。要解决您的问题:

type Vec1<'a> = Vec::<String>;

fn fun1(s1: &String, v1: &mut Vec1) {
    v1.insert(0, s1.clone());
}

fn main() {
    let mut vec1 = Vec::new();
    let str1 = String::new();
    fun1(&str1, &mut vec1);
    println!("{:?}", vec1);
}
Run Code Online (Sandbox Code Playgroud)

该类型不再是引用向量,而是实际对象。在fun1中,向量获得克隆字符串的所有权。

向量具有您创建的类型的另一个示例是这个,但这是有效的,因为编译器可以推断克隆字符串的生命周期。请注意,如果您执行vec1.insert(0, &str1.clone())将不起作用,因为对克隆的引用仅在调用 insert 的生命周期内可用

type Vec1<'a> = Vec::<&'a String>;

fn main() {
    let mut vec1 = Vec::new();
    let str1 = String::new();
    let clone = str1.clone();
    vec1.insert(0, &clone);
    println!("{:?}", vec1);
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

2408 次

最近记录:

1 年,9 月 前