【问题标题】:Rust specify lifetime of local variableRust 指定局部变量的生命周期
【发布时间】:2020-12-31 00:54:57
【问题描述】:

我对 Rust 很陌生,但仍然对生命周期说明符的概念有疑问。

我有一个Vec(或任何其他集合)的参考资料。现在我想用另一个对新创建的局部变量的引用替换一个特定的引用。现在的问题是,本地新变量的生命周期比向量短,这会使引用无效。

尝试做我想做的事但抛出编译时错误的示例代码:

fn main() {
    let values = ["one".to_string(), "lorem".to_string(), "three".to_string()];
    let borrowed_values = vec![&values[0], &values[1], &values[2]];
    println!("{:?}", do_the_impossible(borrowed_values));
}

fn do_the_impossible(mut data: Vec<&String>) -> Vec<&String> {
    let replacement = "two".to_string();
    data[1] = &replacement;
    return data;
}

现在的问题是:如何创建一个与向量具有相同生命周期的新变量?

我想使用引用,因为克隆对象会非常昂贵。

我最初的想法是使用生命周期说明符来指示局部变量应该与向量一样长。但我找不到一种语法正确的方法来做到这一点。甚至可以指定局部变量的生命周期吗?

如果没有,有没有其他方法可以避免克隆向量的元素?我最后的手段是使用Rc 指针。

提前致谢!

【问题讨论】:

  • 这能回答你的问题吗? Is there any way to return a reference to a variable created in a function? tl;dr:不,你不能这样做,在 Rust 或任何语言中。而是返回一个拥有的值。
  • 我想使用引用,因为克隆对象会非常昂贵。 -- 对于刚接触 Rust 的人来说,这是一个相当常见的错误。因为您返回拥有的东西并不意味着它将被克隆。例如,String 是一个拥有 str 的类型,但即使你有一个 String 长一兆字节,从函数返回它最多也只能复制 24 个字节(对于任何 Vec 都相同)。
  • 也许我们彼此误解了,该函数返回一个拥有的 Vec。但是原始的 Vec 并不拥有它的值。我想返回一个有效的 Vec,其中只有一个值被更改,原始的 Vec 保持不变,并且尽可能减少克隆。

标签: rust lifetime


【解决方案1】:

这听起来像是std::borrow::Cow 的一个用例,它允许您拥有一个可以由借用或拥有的值支持的值。

你应该写这样的东西:

use std::borrow::Cow;

fn main() {
    let values = ["one".to_string(), "lorem".to_string(), "three".to_string()];
    let borrowed_values: Vec<_> = values.iter().map(Cow::Borrowed).collect();
    println!("{:?}", do_the_impossible(borrowed_values));
}

fn do_the_impossible<'a>(mut data: Vec<Cow<'a, String>>) -> Vec<Cow<'a, String>> {
    let replacement = "two".to_string();
    data[1] = Cow::Owned(replacement);
    return data;
}

【讨论】:

  • 只是为了检查我是否没有误解某些东西:如果我在 do_the_impossible() 调用之后调用了 borrowed_values.clone() 。是复制值(字符串)还是仅复制引用(牛)?如果 Cow 元素之一是 Cow::Owned 怎么办?价值会被克隆还是借用?
  • 我们可以通过查看Clone for Cow 的实现来发现这一点:doc.rust-lang.org/src/alloc/borrow.rs.html#185-202 - 如果基础价值是借,它将是另一个借,如果基础价值是拥有,它将是它的克隆。如果你想要不同的语义,你也可以实现你自己的Cow 版本——它只是一个enum,它实现了一些有用的特征和功能:)
  • 好的,谢谢,看起来这与我想要的非常接近,可以调整以完全解决我的问题。
猜你喜欢
  • 2018-12-14
  • 2020-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-03
  • 2011-08-06
  • 2013-02-17
  • 1970-01-01
相关资源
最近更新 更多