由于框内

时间:2016-07-07 10:20:44

标签: rust

如果我执行以下操作,则会收到错误消息:

struct A;
struct B;

fn consume_a(_a: A) {}
fn consume_b(_b: B) {}

struct C(A, B);

impl C {
    fn foo(self: Self) {
        consume_a(self.0);
        consume_b(self.1);
    }
}

fn main() {
    let c = Box::new(C(A, B));

    // Consume internals
    let _a = c.0;
    let _b = c.1;
}
error[E0382]: use of moved value: `c`
  --> src/main.rs:21:9
   |
20 |     let _a = c.0;
   |         -- value moved here
21 |     let _b = c.1;
   |         ^^ value used here after move
   |
   = note: move occurs because `c.0` has type `A`, which does not implement the `Copy` trait

我可以做到这一点(消耗内部):

fn main() {
    let c = Box::new(C(A, B));
    c.foo();
}

上面的工作方式(c.foo())意味着我已经移出了盒装内容;怎么会发生这种情况? Box文档中的所有API都没有显示我可以将所包含的值作为类型获取(即所有方法都返回&T&mut T但不返回{{ 1}})

2 个答案:

答案 0 :(得分:6)

正如您在方法中所看到的,移出结构体字段直接可以正常工作,但移出Box中的结构字段将首先移出将Box转换为临时变量,然后移出该临时变量的字段。因此,当您尝试移出第二个字段时,Box已经被破坏,而且只是暂时的左侧,您无法使用。

您可以通过自己创建临时工具来完成这项工作:

let c2 = *c;
let _a = c2.0;
let _b = c2.1;

答案 1 :(得分:2)

启用非词汇生存期时,您的原始代码有效:

#![feature(nll)]

struct A;
struct B;

fn consume_a(_a: A) {}
fn consume_b(_b: B) {}

struct C(A, B);

impl C {
    fn foo(self: Self) {
        consume_a(self.0);
        consume_b(self.1);
    }
}

fn main() {
    let c = Box::new(C(A, B));

    // Consume internals
    let _a = c.0;
    let _b = c.1;
}

这表明原来的失败只是借入检查者的弱点。