猿问

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

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

我试图迭代地导航递归数据结构,以便在某个位置插入元素。据我有限的理解,这意味着对结构的根进行可变的引用,并将其依次替换为对其追随者的引用:

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

这是合情合理的,因为两者anchornode引用相同的结构,但实际上我并不关心anchor在摧毁它之后。

怎么能back()是否正确地使用安全锈蚀来实现?


长风秋雁
浏览 533回答 3
3回答

慕运维8079593

有可能.。但我希望我有一个更优雅的解决方案。诀窍是不要向anchor,因此在两个累加器之间进行操作:保存对当前节点的引用的另一个被分配给下一个节点的引用。这使我想到:impl&nbsp;Recursive&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;back(&mut&nbsp;self)&nbsp;->&nbsp;&mut&nbsp;Link&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;anchor&nbsp;=&nbsp;&mut&nbsp;self.root; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;tmp&nbsp;=&nbsp;anchor; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;let&nbsp;Some(ref&nbsp;mut&nbsp;node)&nbsp;=&nbsp;*tmp&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anchor&nbsp;=&nbsp;&mut&nbsp;node.next; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anchor&nbsp;=&nbsp;tmp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anchor&nbsp;&nbsp;&nbsp;&nbsp;}}不是很漂亮,但这是借阅检查器可以得到的东西,所以wu\_(ツ)_/mr。@ker通过创建一个未命名的临时名称,改进了这一点:impl&nbsp;Recursive&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;back(&mut&nbsp;self)&nbsp;->&nbsp;&mut&nbsp;Link&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;anchor&nbsp;=&nbsp;&mut&nbsp;self.root; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;loop&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;{anchor}&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&mut&nbsp;Some(ref&nbsp;mut&nbsp;node)&nbsp;=>&nbsp;anchor&nbsp;=&nbsp;&mut&nbsp;node.next, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;other&nbsp;=>&nbsp;return&nbsp;other, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}}这里的诀窍是{anchor}&nbsp;移动.的内容anchor进入执行匹配的未命名临时表中。因此,在match我们不能从anchor但是从暂时的,让我们自由修改anchor..参见相关的博客文章填充身份函数所做的(在锈病中).

富国沪深

原始代码的工作方式是-是一次。非词汇寿命启用:#![feature(nll)]type&nbsp;Link&nbsp;=&nbsp;Option<Box<Node>>;struct&nbsp;Node&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;next:&nbsp;Link}struct&nbsp;Recursive&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;root:&nbsp;Link}impl&nbsp;Recursive&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;fn&nbsp;back(&mut&nbsp;self)&nbsp;->&nbsp;&mut&nbsp;Link&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let&nbsp;mut&nbsp;anchor&nbsp;=&nbsp;&mut&nbsp;self.root; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;let&nbsp;Some(node)&nbsp;=&nbsp;anchor&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anchor&nbsp;=&nbsp;&mut&nbsp;node.next; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;anchor&nbsp;&nbsp;&nbsp;&nbsp;}}fn&nbsp;main()&nbsp;{}非词法生命周期提高了编译器的借入检查器的精度,使它能够看到anchor不再使用。我们还可以简化if let由于最近语言的变化。
随时随地看视频慕课网APP
我要回答