首页 文章

混淆了框内结构字段的移动语义

提问于
浏览
5

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

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 但不返回 T

2 回答

  • 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;
    }
    

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

  • 6

    正如您在方法中看到的那样,移出 Box 中的struct 's field directly works fine, but moving out of a field of a struct that'将首先从 Box 移出一个临时变量,然后移出该临时变量的字段 . 因此,当您尝试移出第二个字段时, Box 已经被破坏并且's just a temporary left that you can' t使用了 .

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

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

相关问题