为了账号安全,请及时绑定邮箱和手机立即绑定

在迭代递归结构时无法获得可变引用:一次不能以可变的形式多次借用

在迭代递归结构时无法获得可变引用:一次不能以可变的形式多次借用

在迭代递归结构时无法获得可变引用:一次不能以可变的形式多次借用我试图迭代地导航递归数据结构,以便在某个位置插入元素。据我有限的理解,这意味着对结构的根进行可变的引用,并将其依次替换为对其追随者的引用:type Link = Option<Box<Node>>;struct Node {     next: Link}struct Recursive {     root: Link}impl Recursive {     fn back(&mut self) -> &mut Link {         let mut anchor = &mut self.root;         while let Some(ref mut node) = *anchor {             anchor = &mut node.next;         }         anchor    }}(生锈操场链接)然而,这是失败的:error[E0499]: cannot borrow `anchor.0` as mutable more than once at a time   --> src/main.rs:14:24    | 14 |         while let Some(ref mut node) = *anchor {    |                        ^^^^^^^^^^^^    |                        |    |                        second mutable borrow occurs here    |                        first mutable borrow occurs here ... 18 |     }    |     - first borrow ends here error[E0506]: cannot assign to `anchor` because it is borrowed   --> src/main.rs:15:13    | 14 |         while let Some(ref mut node) = *anchor {    |                        ------------ borrow of `anchor` occurs here 15 |             anchor = &mut node.next;    |             ^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `anchor` occurs here error[E0499]: cannot borrow `*anchor` as mutable more than once at a time   --> src/main.rs:17:9    | 14 |         while let Some(ref mut node) = *anchor {    |                        ------------ first mutable borrow occurs here ... 17 |         anchor    |         ^^^^^^ second mutable borrow occurs here 18 |     }    |     - first borrow ends here这是合情合理的,因为两者anchor和node引用相同的结构,但实际上我并不关心anchor在摧毁它之后。怎么能back()是否正确地使用安全锈蚀来实现?
查看完整描述

3 回答

?
慕运维8079593

TA贡献1876条经验 获得超5个赞

有可能.。但我希望我有一个更优雅的解决方案。

诀窍是不要向anchor,因此在两个累加器之间进行操作:

  • 保存对当前节点的引用的
  • 另一个被分配给下一个节点的引用。

这使我想到:

impl Recursive {
    fn back(&mut self) -> &mut Link {
        let mut anchor = &mut self.root;

        loop {
            let tmp = anchor;
            if let Some(ref mut node) = *tmp {
                anchor = &mut node.next;
            } else {
                anchor = tmp;
                break;
            }
        }

        anchor    }}

不是很漂亮,但这是借阅检查器可以得到的东西,所以wu\_(ツ)_/mr。

@ker通过创建一个未命名的临时名称,改进了这一点:

impl Recursive {
    fn back(&mut self) -> &mut Link {
        let mut anchor = &mut self.root;

        loop {
            match {anchor} {
                &mut Some(ref mut node) => anchor = &mut node.next,
                other => return other,
            }
        }
    }}

这里的诀窍是{anchor} 移动.的内容anchor进入执行匹配的未命名临时表中。因此,在match我们不能从anchor但是从暂时的,让我们自由修改anchor..参见相关的博客文章填充身份函数所做的(在锈病中).


查看完整回答
反对 回复 2019-07-03
?
富国沪深

TA贡献1790条经验 获得超9个赞

原始代码的工作方式是-是一次。非词汇寿命启用:

#![feature(nll)]type Link = Option<Box<Node>>;struct Node {
    next: Link}struct Recursive {
    root: Link}impl Recursive {
    fn back(&mut self) -> &mut Link {
        let mut anchor = &mut self.root;
        while let Some(node) = anchor {
            anchor = &mut node.next;
        }
        anchor    }}fn main() {}

非词法生命周期提高了编译器的借入检查器的精度,使它能够看到anchor不再使用。我们还可以简化if let由于最近语言的变化。


查看完整回答
反对 回复 2019-07-03
  • 3 回答
  • 0 关注
  • 531 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信