首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在不出现“使用移动值”错误的情况下绑定装箱结构的多个字段?

如何在不出现“使用移动值”错误的情况下绑定装箱结构的多个字段?
EN

Stack Overflow用户
提问于 2015-07-14 03:14:42
回答 2查看 649关注 0票数 7

我正在尝试编写一个通用的递归数据结构。事实证明,我不能这样做,因为当我想要访问拥有结构值的多个字段时,我遇到了障碍。

我定义了一个包含列表的结构:

代码语言:javascript
复制
struct ListNode<T> {
    val: T,
    tail: List<T>
}

struct List<T>(Option<Box<ListNode<T>>>);

空列表由List(None)表示。

我希望能够添加到列表中:

代码语言:javascript
复制
impl<T> List<T> {
    fn append(self, val: T) -> List<T> {
        match self {
            List(None) => List(Some(Box::new(ListNode {
                val: val,
                tail: List(None),
            }))),
            List(Some(node)) => List(Some(Box::new(ListNode {
                val: node.val,
                tail: node.tail.append(val),
            }))),
        }
    }
}

此操作将失败,并显示可理解的错误:

代码语言:javascript
复制
error[E0382]: use of moved value: `node`
  --> src/main.rs:17:23
   |
16 |                 val: node.val,
   |                      -------- value moved here
17 |                 tail: node.tail.append(val),
   |                       ^^^^^^^^^ value used here after move
   |
   = note: move occurs because `node.val` has type `T`, which does not implement the `Copy` trait

我寻找了使用结构的多个字段的方法,但我发现了Avoiding partially moved values error when consuming a struct with multiple fields,所以我将这样做:

代码语言:javascript
复制
List(Some(node)) => {
    let ListNode {
        val: nval,
        tail: ntail,
    } = *node;
    List(Some(Box::new(ListNode {
        val: nval,
        tail: ntail.append(val),
    })))
}

嗯,不,还是同样的错误。显然,这不再像在链接中那样工作。

我也尝试过使用refs:

代码语言:javascript
复制
List(Some(node)) => {
    let ListNode {
        val: ref nval,
        tail: ref ntail,
    } = *node;
    List(Some(Box::new(ListNode {
        val: *nval,
        tail: (*ntail).append(val),
    })))
}

这一次解构通过了,但是创建新节点失败了,并显示以下信息:

代码语言:javascript
复制
error[E0507]: cannot move out of borrowed content
  --> src/main.rs:21:26
   |
21 |                     val: *nval,
   |                          ^^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:22:27
   |
22 |                     tail: (*ntail).append(val),
   |                           ^^^^^^^^ cannot move out of borrowed content

我是不是漏掉了什么明显的东西?如果不是,那么访问不是通过引用传递的结构的多个字段的正确方法是什么?我使用的是Rust 1.1。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-07-14 03:42:43

Box之间有一些奇怪的互动。您需要添加一个中间let语句来打开盒子。

代码语言:javascript
复制
List(Some(node)) => {
    let node = *node; // this moves the value from the heap to the stack
    let ListNode { val, tail } = node; // now this works as it should
    List(Some(Box::new(ListNode { val: val, tail: tail.append(value) })))
}

请注意,我将函数参数重命名为value,这样我就可以在不重命名的情况下以简短的形式编写解构。

Try it out in the playground.

票数 6
EN

Stack Overflow用户

发布于 2018-06-21 05:39:58

从Rust 2018开始使用的Non-lexical lifetimes,允许您的原始代码按原样编译:

代码语言:javascript
复制
struct ListNode<T> {
    val: T,
    tail: List<T>
}

struct List<T>(Option<Box<ListNode<T>>>);

impl<T> List<T> {
    fn append(self, val: T) -> List<T> {
        match self {
            List(None) => List(Some(Box::new(ListNode {
                val: val,
                tail: List(None),
            }))),
            List(Some(node)) => List(Some(Box::new(ListNode {
                val: node.val,
                tail: node.tail.append(val),
            }))),
        }
    }
}

fn main() {}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31391581

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档