【问题标题】:Struct update syntax doesn't work on borrowed data结构更新语法不适用于借来的数据
【发布时间】:2017-07-02 18:30:34
【问题描述】:

我有一个这样的结构,带有一些已解析的参数:

struct Args {
    out: Option<String>,
    version: bool,
    help: bool,
    files: Vec<String>,
}

我想递归解析一个列表,每次需要修改时返回一个新修改的Args结构:

fn parse(parsed: &Args, start: usize, args: Vec<String>) -> Args {
    if start >= args.len() {
        return parsed.clone();
    }

    if args[start] == "--version" {
        return parse(&Args { version: true, ..parsed.clone() }, start + 1, args);
    }
    if args[start] == "--help" {
        return parse(&Args { help: true, ..parsed.clone() }, start + 1, args);
    }
    return Args { files: args[start..args.len()].to_vec(), ..parsed.clone() };
}

我使用这样的函数:

fn main() {
    let args = std::env::args().collect::<Vec<String>>();
    let parsed = parse(&Args::default(), 1, args);
}

此代码有效,但我想输入:

return parse(&Args { version: true, ..parsed }, start + 1, args);

代替:

return parse(&Args { version: true, ..parsed.clone() }, start + 1, args);

避免在克隆过程中复制过多的数据。当我删除 .clone() 时,它说应该是 Args 类型,但它却得到了 &amp;Args

当我取消引用 *parsed 时,编译器说“无法移出借用的内容”

【问题讨论】:

  • 您是否考虑过不通过引用传递parsed 参数?
  • @loganfsmyth 是的,我就是这样结束的。我得到的不克隆的速度增益约为 7%。

标签: syntax rust


【解决方案1】:

T 类型为Clone 时,在&amp;T 上调用clone() 也将返回T,因为仅仅复制指针是没有意义的。事实上,如果它确实克隆了底层数据,然后返回了对它的引用,那么你就会遇到麻烦,因为T 会被删除,指针悬空。

要将&amp;T 转换为T,您可以使用* 运算符取消引用它。但是,这会给您带来问题,因为parsed 是由parse 函数借用的,这意味着它必须在完成后将其归还。如果您取消引用它并移动值,那么您将脱离借用的上下文。

【讨论】:

  • 取消引用不起作用 - 它说“无法移出借用的内容”。
  • 这就是我所说的! 我的意思可能有点歪曲,但这个错误应该告诉你一些事情。您要么首先需要将对象移动到parse,而不是传递引用,否则您将无法进行克隆。
  • 如果我们可以让 rust 以某种方式在这个地方接受借来的引用,这很有趣 - 我看不出有什么理由不这样做。
  • 您想借用参考,然后移动各个字段!例如,一旦您将files 向量移动到新的Args 实例上,那么原来的实例将不再拥有它们。即使您的程序不需要它们,Rust 也不允许您传递其中包含空指针的结构。您通常不需要太担心克隆的性能 - 优化器做得非常好,以至于它通常与不克隆相同。因此,如果它成为问题,请处理它。
  • 那么,struct的内部也算是借来的,不能随便用吧?我得到了它。呃……手动内存管理是我十五年没碰过的东西。 :D 谢谢!
猜你喜欢
  • 2022-09-25
  • 2011-11-13
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
  • 1970-01-01
  • 2020-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多